MD2, MD4 and MD5 are weak hash functions
Bug Pattern: WEAK_MESSAGE_DIGEST_MD5
The algorithms MD2, MD4 and MD5 are not a recommended MessageDigest. PBKDF2 should be used to hash password for example.
“The security of the MD5 hash function is severely compromised. A collision attack exists that can find collisions within seconds on a computer with a 2.6 GHz Pentium 4 processor (complexity of 224.1).[1] Further, there is also a chosen-prefix collision attack that can produce a collision for two inputs with specified prefixes within hours, using off-the-shelf computing hardware (complexity 239).[2]”
Wikipedia: MD5 - Security
“SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256:
The use of these hash functions is acceptable for all hash function applications.”NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths p.15
“The main idea of a PBKDF is to slow dictionary or brute force attacks on the passwords by increasing the time needed to test each password. An attacker with a list of likely passwords can evaluate the PBKDF using the known iteration counter and the salt. Since an attacker has to spend a significant amount of computing time for each try, it becomes harder to apply the dictionary or brute force attacks.”NIST: Recommendation for Password-Based Key Derivation p.12
Vulnerable Code:
MessageDigest md5Digest = MessageDigest.getInstance(“MD5”);
md5Digest.update(password.getBytes());
byte[] hashValue = md5Digest.digest();
byte[] hashValue = DigestUtils.getMd5Digest().digest(password.getBytes());
Solution (Using bouncy castle):
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());
gen.init(password.getBytes(“UTF-8”), salt.getBytes(), 4096);
return ((KeyParameter) gen.generateDerivedParameters(256)).getKey();
}
Solution (Java 8 and later):
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 4096, 256 * 8);
SecretKeyFactory f = SecretKeyFactory.getInstance(“PBKDF2WithHmacSHA256”);
return f.generateSecret(spec).getEncoded();
}
References
[1] On Collisions for MD5: Master Thesis by M.M.J. Stevens
[2] Chosen-prefix collisions for MD5 and applications: Paper written by Marc Stevens
Wikipedia: MD5
NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths
NIST: Recommendation for Password-Based Key Derivation
Stackoverflow: Reliable implementation of PBKDF2-HMAC-SHA256 for Java
CWE-327: Use of a Broken or Risky Cryptographic Algorithm
SHA-1 is a weak hash function
Bug Pattern: WEAK_MESSAGE_DIGEST_SHA1
The algorithms SHA-1 is not a recommended algorithm for hash password, for signature verification and other uses. PBKDF2 should be used to hash password for example.
“SHA-1 for digital signature generation:
SHA-1 may only be used for digital signature generation where specifically allowed by NIST protocol-specific guidance. For all other applications, SHA-1 shall not be used for digital signature generation.
SHA-1 for digital signature verification:
For digital signature verification, SHA-1 is allowed for legacy-use.
[…]
SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256:
The use of these hash functions is acceptable for all hash function applications.”
NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths p.15
“The main idea of a PBKDF is to slow dictionary or brute force attacks on the passwords by increasing the time needed to test each password. An attacker with a list of likely passwords can evaluate the PBKDF using the known iteration counter and the salt. Since an attacker has to spend a significant amount of computing time for each try, it becomes harder to apply the dictionary or brute force attacks.”NIST: Recommendation for Password-Based Key Derivation p.12
Vulnerable Code:
MessageDigest sha1Digest = MessageDigest.getInstance(“SHA1”);
sha1Digest.update(password.getBytes());
byte[] hashValue = sha1Digest.digest();
byte[] hashValue = DigestUtils.getSha1Digest().digest(password.getBytes());
Solution (Using bouncy castle):
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());
gen.init(password.getBytes(“UTF-8”), salt.getBytes(), 4096);
return ((KeyParameter) gen.generateDerivedParameters(256)).getKey();
}
Solution (Java 8 and later):
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 4096, 256 * 8);
SecretKeyFactory f = SecretKeyFactory.getInstance(“PBKDF2WithHmacSHA256”);
return f.generateSecret(spec).getEncoded();
}
References
Qualys blog: SHA1 Deprecation: What You Need to Know
Google Online Security Blog: Gradually sunsetting SHA-1
NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths
NIST: Recommendation for Password-Based Key Derivation
Stackoverflow: Reliable implementation of PBKDF2-HMAC-SHA256 for Java
CWE-327: Use of a Broken or Risky Cryptographic Algorithm