Insecure SHA1 Hash (PyCryptodome)

MEDIUM

SHA-1 was broken by the SHAttered collision attack in 2017 and is deprecated by NIST for digital signatures. Use SHA-256 or SHA-3 via PyCryptodome instead.

Rule Information

Language
Python
Category
Cryptography
Author
Shivasurya
Shivasurya
Last Updated
2026-03-22
Tags
pythonpycryptodomesha1weak-hashCWE-327OWASP-A02
CWE References

Interactive Playground

Experiment with the vulnerable code and security rule below. Edit the code to see how the rule detects different vulnerability patterns.

pathfinder scan --ruleset python/PYTHON-CRYPTO-SEC-015 --project .
1
2
3
4
5
6
rule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

About This Rule

Understanding the vulnerability and how it is detected

Detects usage of SHA-1 via the PyCryptodome library using any of its SHA-1 module aliases: `Crypto.Hash.SHA.new()`, `Cryptodome.Hash.SHA.new()`, `Crypto.Hash.SHA1.new()`, or `Cryptodome.Hash.SHA1.new()`. PyCryptodome exposes SHA-1 under both the older `SHA` name (for historical compatibility with PyCrypto) and the explicit `SHA1` name.

SHA-1 produces a 160-bit digest and was formally broken in 2017 when Stevens et al. at CWI Amsterdam and Google produced the first known SHA-1 collision (SHAttered attack). A chosen-prefix collision attack was demonstrated in 2020 at a cost of approximately 900 GPU-years, making targeted forgery feasible for well-resourced adversaries.

NIST deprecated SHA-1 for digital signatures in SP 800-131A and FIPS 186-5 removes SHA-1 entirely from approved signature algorithms. Browser vendors stopped trusting SHA-1 TLS certificates in 2017.

SHA-1 must not be used for digital signatures, certificate hashing, HMAC authentication, or data integrity in security contexts. It is sometimes encountered in PyCryptodome codebases because older PyCrypto tutorials used `from Crypto.Hash import SHA` — this rule catches both the legacy `SHA` alias and the explicit `SHA1` module name.

Security Implications

Potential attack scenarios if this vulnerability is exploited

1

2

3

4

How to Fix

Recommended remediation steps

  • 1Replace Crypto.Hash.SHA.new() and Crypto.Hash.SHA1.new() with Crypto.Hash.SHA256.new() for all integrity, signing, and authentication use cases.
  • 2Use Crypto.Hash.SHA3_256.new() or Crypto.Hash.SHA3_512.new() when stronger collision resistance or independence from SHA-2 is needed.
  • 3For password hashing, do not use SHA-1 or any raw hash — use Argon2id (argon2-cffi), bcrypt, or scrypt.
  • 4Update any HMAC usage from HMAC with SHA-1 to HMAC with SHA-256: `HMAC.new(key, digestmod=SHA256)` instead of `HMAC.new(key, digestmod=SHA)`.
  • 5If SHA-1 is required by a legacy file format or protocol you cannot modify, isolate the usage, document it explicitly, and apply compensating controls such as an outer SHA-256 HMAC over the data.

Detection Scope

How Code Pathfinder analyzes your code for this vulnerability

Matches any call to `PyCryptoHashSHA.method("new")` where `PyCryptoHashSHA` is a QueryType resolving fully-qualified names `Crypto.Hash.SHA`, `Cryptodome.Hash.SHA`, `Crypto.Hash.SHA1`, and `Cryptodome.Hash.SHA1`. This covers all four naming variants that PyCryptodome exposes for SHA-1, ensuring detection regardless of whether code uses the legacy `SHA` alias (from PyCrypto era) or the explicit `SHA1` module name. The rule fires on `.new()` constructor invocation in either namespace.

Compliance & Standards

Industry frameworks and regulations that require detection of this vulnerability

OWASP Top 10
A02:2021 - Cryptographic Failures
PCI DSS v4.0
Requirement 4.2.1 -- use strong cryptography
NIST SP 800-131A
MD5 and SHA-1 disallowed for digital signatures
NIST SP 800-53
SC-13: Cryptographic Protection

References

External resources and documentation

Similar Rules

Explore related security rules for Python

Frequently Asked Questions

Common questions about Insecure SHA1 Hash (PyCryptodome)

SHA-1 is acceptable only for non-security legacy compatibility contexts where collision resistance is not a security requirement — for example, computing Git-style content identifiers in tooling that is not security-sensitive. It must not be used for digital signatures, HMAC, certificate hashing, or password hashing.
PYTHON-CRYPTO-SEC-011 targets SHA-1 used via the `cryptography` library hazmat interface (hashes.SHA1()). This rule (PYTHON-CRYPTO-SEC-015) targets SHA-1 in PyCryptodome via Crypto.Hash.SHA.new() or Crypto.Hash.SHA1.new(). The underlying weakness is identical; the rules differ by library.
PyCryptodome inherited the `SHA` module name from the original PyCrypto library, where `from Crypto.Hash import SHA` was the canonical way to import SHA-1. PyCryptodome also provides the explicit `SHA1` name. Both resolve to the same SHA-1 algorithm. This rule catches both to handle both modern and legacy import styles.
SHA-256 is designed to be fast, which benefits attackers performing brute-force attacks. Use Argon2id, bcrypt, or scrypt for password hashing — these are deliberately slow and memory-intensive to limit attacker throughput to thousands of attempts per second rather than billions.
Yes, if Crypto.Hash.SHA or Crypto.Hash.SHA1 is used as the digestmod for an HMAC. While HMAC-SHA1 is not broken by collision attacks, it is deprecated in current standards and should be replaced with HMAC-SHA256.
Run `code-pathfinder scan --ruleset python/cryptography/PYTHON-CRYPTO-SEC-015 --path ./src` in your pipeline. Add `--format sarif` to produce SARIF output compatible with GitHub Advanced Security and similar platforms.
Prioritize eliminating SHA-1 from: (1) digital signatures and certificate generation first, (2) HMAC authentication second, (3) data integrity checks third. Non-security uses such as content identifiers can be addressed last. Document all retained uses with a migration timeline and review compensating controls.

New feature

Get these findings posted directly on your GitHub pull requests

The Insecure SHA1 Hash (PyCryptodome) rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.

See how it works