# PYTHON-CRYPTO-SEC-023: Insufficient RSA Key Size (PyCryptodome)

> **Severity:** HIGH | **CWE:** CWE-326 | **OWASP:** A02:2021

- **Language:** Python
- **Category:** Cryptography
- **URL:** https://codepathfinder.dev/registry/python/cryptography/PYTHON-CRYPTO-SEC-023
- **Detection:** `pathfinder scan --ruleset python/PYTHON-CRYPTO-SEC-023 --project .`

## Description

Detects RSA key generation using `RSA.generate(bits)` from PyCryptodome where the first positional argument (key size in bits) is less than 3072. This rule uses a `.where(0, lt(3072))` predicate targeting position 0 of the call — it fires only on provably undersized keys and does not flag 3072-bit or larger keys.
The 3072-bit threshold is deliberately stricter than the SEC-020 `cryptography` library rule (which uses 2048 as the floor). PyCryptodome's own documentation recommends 3072-bit keys for new applications to ensure adequate security beyond 2030. NIST SP 800-57 equates 3072-bit RSA to 128-bit symmetric security. A 2048-bit RSA key provides only 112-bit security and is scheduled for deprecation by NIST after 2030. RSA keys shorter than 3072 bits are vulnerable to the General Number Field Sieve factorization algorithm given sufficient compute. For new systems, consider ECDSA with SECP256R1 or SECP384R1 which provides equivalent or stronger security with significantly shorter keys.


## Vulnerable Code

```python
from Crypto.PublicKey import RSA

key = RSA.generate(1024)
```

## Secure Code

```python
from Crypto.PublicKey import RSA

# SECURE: RSA 3072-bit key (NIST 128-bit security, recommended minimum)
key = RSA.generate(3072)

# SECURE: RSA 4096-bit key (preferred for long-lived keys and certificates)
key = RSA.generate(4096)

# PREFERRED: Use ECDSA instead of RSA for new systems
from Crypto.PublicKey import ECC
key = ECC.generate(curve='P-384')

```

## Detection Rule (Python SDK)

```python
from rules.python_decorators import python_rule
from codepathfinder import calls, flows, QueryType
from codepathfinder.qualifiers import lt


class PyCryptoRSA(QueryType):
    fqns = ["Crypto.PublicKey.RSA", "Cryptodome.PublicKey.RSA"]


@python_rule(
    id="PYTHON-CRYPTO-SEC-023",
    name="Insufficient RSA Key Size (PyCryptodome)",
    severity="HIGH",
    category="cryptography",
    cwe="CWE-326",
    tags="python,pycryptodome,rsa,key-size,CWE-326,OWASP-A02",
    message="RSA key size is less than 3072 bits. PyCryptodome recommends 3072+ bit keys.",
    owasp="A02:2021",
)
def detect_rsa_keygen_pycrypto():
    """Detects RSA key generation with insufficient key size in PyCryptodome."""
    return PyCryptoRSA.method("generate").where(0, lt(3072))
```

## How to Fix

- Use RSA.generate(3072) as the minimum for PyCryptodome RSA key generation.
- Use RSA.generate(4096) for long-lived keys such as CA certificates or signing keys.
- Consider replacing RSA with ECC — ECC.generate(curve='P-256') provides equivalent security to RSA-3072 with a 256-bit key.
- Note that this rule is stricter than SEC-020 (cryptography lib) which uses 2048 as the floor; aligning on 3072 ensures systems will remain compliant beyond 2030.
- Audit all RSA key material in your infrastructure and schedule rotation of any keys below 3072 bits on a risk-based timeline.

## FAQ

**Q: Does this rule flag RSA.generate(2048)?**

Yes. This rule flags keys below 3072 bits, so RSA.generate(2048) will trigger a finding. This is intentionally stricter than SEC-020 (which only flags below 2048). The 3072-bit threshold reflects NIST's recommendation for systems expected to operate beyond 2030 and PyCryptodome's own documentation guidance.


**Q: Why does SEC-023 flag below 3072 while SEC-020 flags below 2048?**

SEC-020 targets the `cryptography` library and uses 2048 bits as the hard regulatory minimum per NIST SP 800-131A. SEC-023 targets PyCryptodome and applies a forward-looking threshold of 3072 bits, reflecting PyCryptodome's own recommendation for new applications and NIST's guidance that 2048-bit provides only 112-bit security (acceptable until 2030, not beyond). This difference helps teams building new systems avoid creating key material that will require imminent rotation.


**Q: What key size should I use for new applications?**

Use RSA.generate(3072) as the minimum for new PyCryptodome applications. Use RSA.generate(4096) for long-lived certificates or any key protecting data beyond 2030. Alternatively migrate to ECC — ECC.generate(curve='P-256') provides 128-bit security with a much shorter key and faster operations.


**Q: Is RSA.generate(2048) safe right now?**

Technically 2048-bit RSA meets current NIST minimums and will until 2030. However, PyCryptodome's documentation explicitly recommends 3072-bit for new applications, and this rule enforces that recommendation. If you have 2048-bit keys in existing systems you should plan rotation before 2030; do not generate new 2048-bit keys.


**Q: What attack does a sub-3072 RSA key enable?**

RSA keys are broken by factoring the modulus N = p * q. The General Number Field Sieve (GNFS) algorithm has a sub-exponential runtime that makes 1024-bit keys factorable and puts 2048-bit keys at increasing risk as compute costs fall. Once factored, all past ciphertext encrypted with that key can be decrypted (no forward secrecy), and signatures can be forged.


**Q: Does PyCryptodome enforce any minimum key size internally?**

PyCryptodome does not enforce a minimum key size by default. RSA.generate(512) will succeed without warning. This rule compensates for that missing guard at the code analysis layer.


**Q: How does this rule detect the key size in positional argument calls?**

PyCryptodome's `RSA.generate(bits)` accepts key size as position 0. The rule uses `.where(0, lt(3072))` to filter on the first positional argument. If the key size is passed as a variable whose value cannot be statically resolved, this rule may not fire (under-approximation). Consider using named constants or literal values for key sizes.


## References

- [CWE-326: Inadequate Encryption Strength](https://cwe.mitre.org/data/definitions/326.html)
- [NIST SP 800-57 Part 1 Rev 5: Recommendation for Key Management](https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
- [NIST SP 800-131A Rev 2: Transitioning the Use of Cryptographic Algorithms and Key Lengths](https://csrc.nist.gov/publications/detail/sp/800-131a/rev-2/final)
- [PyCryptodome Documentation: RSA.generate()](https://pycryptodome.readthedocs.io/en/latest/src/public_key/rsa.html)
- [OWASP Cryptographic Failures (A02:2021)](https://owasp.org/Top10/A02_2021-Cryptographic_Failures/)

---

Source: https://codepathfinder.dev/registry/python/cryptography/PYTHON-CRYPTO-SEC-023
Code Pathfinder — Open source, type-aware SAST with cross-file dataflow analysis
