# PYTHON-CRYPTO-SEC-021: Insufficient DSA Key Size (cryptography lib)

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

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

## Description

Detects DSA key generation using `dsa.generate_private_key()` from the `cryptography` library where the `key_size` argument is less than 2048 bits. This rule uses a `.where("key_size", lt(2048))` predicate and fires only on provably undersized keys; it does not flag 2048-bit or larger keys. DSA with small keys is vulnerable to discrete logarithm attacks: with a 1024-bit modulus an attacker can recover the private key and then forge arbitrary signatures on any message. NIST SP 800-131A formally deprecated 1024-bit DSA in 2013 and requires 2048-bit minimum. Note that DSA itself is being phased out in favour of ECDSA — even at 2048 bits, DSA requires careful nonce management (a reused nonce leaks the private key as demonstrated in Sony PlayStation 3 key extraction). For new systems prefer ECDSA with SECP256R1 or EdDSA.


## Vulnerable Code

```python
from cryptography.hazmat.primitives.asymmetric import rsa, dsa, ec
from cryptography.hazmat.backends import default_backend

# SEC-021: DSA key generation (audit)
dsa_key = dsa.generate_private_key(
    key_size=1024,
    backend=default_backend()
)
```

## Secure Code

```python
from cryptography.hazmat.primitives.asymmetric import dsa, ec
from cryptography.hazmat.backends import default_backend

# SECURE: DSA 2048-bit key (NIST minimum)
private_key = dsa.generate_private_key(
    key_size=2048,
    backend=default_backend()
)

# SECURE: DSA 3072-bit key (recommended for post-2030)
private_key = dsa.generate_private_key(
    key_size=3072,
    backend=default_backend()
)

# PREFERRED: ECDSA P-256 — replaces DSA for new systems, immune to nonce reuse issues
private_key = ec.generate_private_key(ec.SECP256R1(), backend=default_backend())

```

## Detection Rule (Python SDK)

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


class CryptoDSA(QueryType):
    fqns = ["cryptography.hazmat.primitives.asymmetric.dsa"]


@python_rule(
    id="PYTHON-CRYPTO-SEC-021",
    name="Insufficient DSA Key Size",
    severity="HIGH",
    category="cryptography",
    cwe="CWE-326",
    tags="python,cryptography,dsa,key-size,CWE-326,OWASP-A02",
    message="DSA key size is less than 2048 bits. Use at least 2048-bit keys.",
    owasp="A02:2021",
)
def detect_dsa_keygen_crypto():
    """Detects DSA key generation with insufficient key size in cryptography lib."""
    return CryptoDSA.method("generate_private_key").where("key_size", lt(2048))
```

## How to Fix

- Use key_size=2048 as the absolute minimum; use key_size=3072 for systems expected to operate beyond 2030.
- Consider replacing DSA with ECDSA (SECP256R1) or EdDSA for new applications — smaller keys, faster operations, and no nonce-reuse catastrophe.
- If DSA must be used, ensure the per-signature nonce (k) is generated with a cryptographically secure random number generator; a reused nonce leaks the private key.
- Audit all DSA key material in your infrastructure and schedule rotation of any keys below 2048 bits.

## FAQ

**Q: Does this rule flag 2048-bit DSA keys?**

No. The rule uses `.where("key_size", lt(2048))` which only fires when key_size is strictly less than 2048 bits. A key_size=2048 call does NOT trigger this rule.


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

Use 2048-bit DSA at minimum, or 3072-bit for systems requiring protection beyond 2030. However, for any new system consider replacing DSA entirely with ECDSA using SECP256R1 (equivalent to 3072-bit RSA/DSA) or EdDSA (Ed25519). These are faster, have smaller key and signature sizes, and EdDSA is immune to nonce reuse vulnerabilities.


**Q: Why is DSA particularly risky compared to RSA?**

DSA signing requires a random nonce (k) per signature. If that nonce is ever reused across two signatures, an attacker can algebraically recover the private key — even if the key itself is 4096 bits. This attack was used in 2010 to extract the Sony PS3 master signing key. ECDSA shares this property; EdDSA (Ed25519) deterministically derives nonces and is immune.


**Q: What attack does a small DSA key enable?**

Small DSA keys are vulnerable to the index calculus algorithm for computing discrete logarithms over the underlying finite field. With a 1024-bit modulus, an attacker can recover the private key and then forge signatures on arbitrary messages, enabling them to impersonate the key holder for code signing, authentication, or certificate issuance.


**Q: Why does this rule flag below 2048 while SEC-024 (PyCryptodome) also flags below 2048?**

Both SEC-021 and SEC-024 use 2048 bits as the threshold, aligning with the NIST SP 800-131A minimum. The only difference is the library being targeted: SEC-021 targets the `cryptography` library's `dsa.generate_private_key(key_size=...)` API, while SEC-024 targets PyCryptodome's `DSA.generate(bits)` API where key size is a positional argument.


**Q: Is DSA still acceptable for compliance purposes?**

Yes, 2048-bit DSA remains acceptable under most compliance frameworks through 2030. However, NIST SP 800-131A notes that DSA is losing support across implementations. OpenSSH deprecated DSA host keys in version 7.0 (2015). Check your compliance framework's current approved algorithm list before committing to DSA for new systems.


## 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)
- [Sony PS3 DSA Nonce Reuse Attack (2010) — private key recovered from two signatures](https://www.bbc.co.uk/news/technology-12116051)
- [OWASP Cryptographic Failures (A02:2021)](https://owasp.org/Top10/A02_2021-Cryptographic_Failures/)

---

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