Use of a weak or non-cryptographic hash algorithm
ID |
dart.cryptography.weak_hash_algorithm |
Severity |
high |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
medium |
Resource |
Cryptography |
Language |
Dart |
Description
A broken or non-cryptographic hash algorithm (MD2, MD4, MD5, SHA-1, RIPEMD-128, Tiger, CRC, FNV, etc.) is used in a security context. Collisions or pre-image attacks let an attacker forge data that produces the same digest as a legitimate input, defeating integrity and signing guarantees.
Rationale
Hash algorithms in this category are either fully broken (MD2, MD4, MD5, SHA-1 all have practical chosen-prefix or chosen-suffix collision attacks — see SHAttered, MD5 chosen-prefix collisions used in the Flame malware certificate forgery) or were never intended for security (CRC32, FNV, Adler32 are checksums for error detection, not adversarial resistance). Tiger and RIPEMD-128 lack any modern analysis margin.
In a Flutter app the most common security uses of a hash are HMAC keys, signature verification, JWT signing/validation, certificate pinning fingerprints, and content-integrity tokens. Each of these relies on the impossibility of finding two inputs with the same digest — exactly the property these algorithms have lost. An attacker who can craft input that collides with a legitimate value can forge tokens, bypass pin checks, or substitute a malicious payload that still validates against a stored hash.
The following code illustrates a vulnerable pattern detected by this rule:
class WeakHashes {
// ===== package:crypto — top-level Hash instances =====
void packageCryptoUnprefixed(String s) {
// VULNERABLE: Use of a weak or non-cryptographic hash algorithm
final h1 = md5.convert(utf8.encode(s));
// VULNERABLE: Use of a weak or non-cryptographic hash algorithm
final h2 = sha1.convert(utf8.encode(s));
print('$h1 $h2');
}
}
Remediation
Replace the weak hash with a modern cryptographic hash: SHA-256,
SHA-384, SHA-512, SHA-3 (Keccak), or BLAKE2/BLAKE3. For HMAC, use
the same modern hash inside the HMAC construction. For password
hashing specifically, use a memory-hard KDF (Argon2id, scrypt,
bcrypt, or PBKDF2 with >= 600 000 iterations) — see
weak_password_hash.
import 'package:crypto/crypto.dart';
import 'dart:convert';
// Vulnerable: MD5 / SHA-1
final h = md5.convert(utf8.encode(data));
final m = Hmac(sha1, key).convert(payload);
// Fixed: SHA-256 or stronger
final h = sha256.convert(utf8.encode(data));
final m = Hmac(sha256, key).convert(payload);
References
-
OWASP Top 10 2025 - A04 : Cryptographic Failures.
-
OWASP Cryptographic Storage Cheat Sheet — Modern hash recommendations and decision tree for picking an algorithm
-
Talsec — OWASP Mobile Top 10 for Flutter M10 — Insufficient cryptography in Flutter / Dart with concrete weak-hash examples
-
package:crypto (pub.dev) — Dart team’s hashing API — exposes
sha256/sha512/Hmacas safe defaults -
package:pointycastle (pub.dev) — Full crypto suite — prefer SHA-256/SHA-3/BLAKE2 digest classes over MD5/SHA-1/RIPEMD-128