Insecure MD2 Hash (PyCryptodome)

HIGH

MD2 is an obsolete 1989 algorithm with known preimage attacks, extremely poor performance, and no valid modern use case. Use SHA-256 or SHA-3 instead.

Rule Information

Language
Python
Category
Cryptography
Author
Shivasurya
Shivasurya
Last Updated
2026-03-22
Tags
pythonpycryptodomemd2weak-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-014 --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

About This Rule

Understanding the vulnerability and how it is detected

Detects usage of MD2 via PyCryptodome's `Crypto.Hash.MD2.new()` or `Cryptodome.Hash.MD2.new()` constructor. MD2 was designed by Ron Rivest in 1989 and is the oldest of the MD family. It was deprecated by the IETF in RFC 6149 in 2011 with the explicit recommendation that it "SHOULD NOT be used."

MD2 produces a 128-bit digest but uses an 8-bit oriented design with a permutation table that makes it extremely slow compared to all modern alternatives. Muller (2004) demonstrated a preimage attack reducing work to 2^104, well below MD2's intended 2^128 security level. Knudsen and Mathiassen published further weaknesses. The algorithm has no collision resistance properties appropriate for modern use.

Unlike MD5 which sees legitimate non-security use as a fast checksum, MD2 is so slow and so thoroughly analyzed for weaknesses that there is no context in which it is preferable to a modern algorithm. Any appearance of MD2 in a codebase indicates either extreme legacy code (e.g., old X.509 certificate parsing from early-1990s PKI) or a mistake.

This rule is rated HIGH severity because MD2 combines known cryptographic weaknesses with zero remaining legitimate use cases and no performance rationale for its selection.

Security Implications

Potential attack scenarios if this vulnerability is exploited

1

2

3

4

How to Fix

Recommended remediation steps

  • 1Replace Crypto.Hash.MD2.new() with Crypto.Hash.SHA256.new() — SHA-256 is faster, stronger, and universally supported.
  • 2For password hashing, use Argon2id (argon2-cffi), bcrypt, or scrypt rather than any raw hash function including SHA-256.
  • 3If the code is parsing legacy X.509 certificates that use MD2withRSA signatures, use a modern TLS/PKI library that correctly rejects MD2-signed certificates rather than reimplementing the verification.
  • 4Audit all call sites thoroughly — any code using MD2 is likely very old and may contain other cryptographic weaknesses worth reviewing.
  • 5Use Crypto.Hash.HMAC with SHA-256 as the digest module for message authentication codes rather than any MD-family algorithm.

Detection Scope

How Code Pathfinder analyzes your code for this vulnerability

Matches any call to `PyCryptoHashMD2.method("new")` where `PyCryptoHashMD2` is a QueryType resolving fully-qualified names `Crypto.Hash.MD2` and `Cryptodome.Hash.MD2`. This covers both the PyCryptodome drop-in compatibility namespace (`Crypto.*`) and the standalone namespace (`Cryptodome.*`). The rule fires on `.new()` constructor invocation. Any detection of this rule in production code warrants immediate review — legitimate current uses of MD2.new() are virtually nonexistent outside of legacy protocol parsers for early-1990s X.509 formats.

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 MD2 Hash (PyCryptodome)

No. MD2 has known preimage attacks, no performance advantage, and was formally deprecated by RFC 6149 in 2011. There is no context — including non-security checksums — where MD2 is preferable to a modern algorithm. Replace all uses unconditionally.
MD2 is the oldest (1989) and uses an 8-bit oriented design with a permutation lookup table. It is significantly slower than MD4 and MD5 on general-purpose hardware. It also has weaker preimage resistance due to Muller's 2004 attack. MD4 and MD5 were designed as faster, more modern alternatives to MD2 but are themselves now broken.
Most commonly: (1) copied from extremely old legacy code without review, (2) parsing or re-implementing early-1990s X.509 certificate formats, or (3) academic or protocol testing code. None of these justify using MD2 in production security paths.
RFC 6149 (2011) titled 'MD2 to Historic Status' explicitly states that MD2 'SHOULD NOT be used' and that 'It is not suitable for use in new applications.' This is the IETF's strongest deprecation language short of 'MUST NOT.'
MD5 retains limited legitimate non-security uses (fast checksums) and its collision attacks, while practical, require more effort than MD2 attacks. MD2 has known preimage attacks (not just collision attacks), no performance benefits, and zero legitimate modern use cases. The combination of deeper weakness and no redemptive use case justifies HIGH severity.
Run `code-pathfinder scan --ruleset python/cryptography/PYTHON-CRYPTO-SEC-014 --path ./src` in your pipeline. Add `--format sarif` to produce SARIF output compatible with GitHub Advanced Security and similar platforms.
Check whether the library uses MD2 in a security-sensitive path. If it does, file a bug with the library maintainer, pin to a version that does not use MD2 if possible, or replace the dependency. If the library uses MD2 only for parsing legacy formats and your code does not pass untrusted data through that path, document the residual risk.

New feature

Get these findings posted directly on your GitHub pull requests

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

See how it works