← Back to Advanced Java Course | Chapter 11: Advanced & Security | Lesson 12 of 19

Java Hashing (MD5, SHA)

Hashing turns any data into a short fixed fingerprint, so you can check whether it has changed. It cannot be turned back, which makes it useful for passwords.
Syntax
java
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));

What is Hashing?

Hashing converts arbitrary input data into a fixed-length string of characters that acts as a unique mathematical fingerprint of that data. It's a deliberately one-way process -- there's no algorithm to reverse a hash back into its original input, which is exactly the property that makes it useful for verifying data or storing passwords.

Example: What is Hashing?

java
import java.security.MessageDigest;
public class Main {
	public static void main(String[] args) throws Exception {
		MessageDigest digest = MessageDigest.getInstance("SHA-256");
		byte[] hash = digest.digest("hello".getBytes());
		System.out.println("Fixed length: " + hash.length + " bytes"); // one-way, no reverse algorithm exists
	}
}

MD5 Hashing

MD5 is a legacy, 128-bit hashing algorithm. It's fast, but it has well-documented cryptographic vulnerabilities (including practical collision attacks), so it should never be used to secure passwords or anything else where security actually matters today.

Example: MD5 Hashing

java
import java.security.MessageDigest;
public class Main {
	public static void main(String[] args) throws Exception {
		MessageDigest digest = MessageDigest.getInstance("MD5"); // fast but has known collision attacks
		byte[] hash = digest.digest("data".getBytes());
		System.out.println(hash.length + " bytes -- never use for passwords");
	}
}

SHA-256 Hashing

SHA-256 is a secure, 256-bit hashing algorithm from the SHA-2 family. It's currently the standard choice for data integrity verification and general cryptographic checks, since no practical attack against it is known at the time of writing.

Example: SHA-256 Hashing

java
import java.security.MessageDigest;
public class Main {
	public static void main(String[] args) throws Exception {
		MessageDigest digest = MessageDigest.getInstance("SHA-256"); // current standard for integrity checks
		byte[] hash = digest.digest("data".getBytes());
		StringBuilder hex = new StringBuilder();
		for (byte b : hash) hex.append(String.format("%02x", b));
		System.out.println(hex);
	}
}

Password Salting

Salting adds a random value (the salt) to a password before hashing it, and stores that salt alongside the resulting hash. This protects against precomputed rainbow-table attacks, since it ensures two users with the identical password still end up with completely different stored hashes.

Example: Password Salting

java
import java.security.*;
public class Main {
	public static void main(String[] args) throws Exception {
		SecureRandom random = new SecureRandom();
		byte[] salt = new byte[16];
		random.nextBytes(salt); // random per user, stored alongside the hash
		MessageDigest digest = MessageDigest.getInstance("SHA-256");
		digest.update(salt);
		byte[] hash = digest.digest("password123".getBytes());
		System.out.println("Salted hash length: " + hash.length);
	}
}

Verifying Hashes

To verify a password later, you regenerate the hash of the newly submitted input using the same algorithm and the same stored salt, then compare the resulting bytes against the stored hash -- never by comparing the original plaintext passwords directly.

Example: Verifying Hashes

java
import java.security.*;
import java.util.Arrays;
public class Main {
	public static void main(String[] args) throws Exception {
		byte[] salt = "fixedSaltForDemo".getBytes();
		MessageDigest digest = MessageDigest.getInstance("SHA-256");
		digest.update(salt);
		byte[] storedHash = digest.digest("password123".getBytes());
		digest.reset();
		digest.update(salt);
		byte[] submittedHash = digest.digest("password123".getBytes()); // recomputed with the same salt
		System.out.println(Arrays.equals(storedHash, submittedHash));
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Storing passwords with plain MD5 or SHA-256, when these are too fast and password storage needs a slow algorithm like bcrypt or PBKDF2.
  2. Hashing passwords without a random salt, so equal passwords give equal hashes and rainbow tables work.
  3. Calling getBytes() without a charset, which uses the platform default and can give different hashes on different machines; use StandardCharsets.UTF_8.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.