Cryptographic Hashing with MessageDigest
Hash passwords with SHA-256, add salt to prevent rainbow table attacks, and compare digests securely.
Cryptographic Hashing with MessageDigest is a free Java Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is Cryptographic Hashing?
A cryptographic hash function maps data of any size to a fixed-size digest. It is one-way (cannot be reversed), deterministic, and collision-resistant. Used for password storage, data integrity, and digital signatures.
MessageDigest API
MessageDigest.getInstance("SHA-256") returns a SHA-256 digester. Call digest(bytes) to compute the hash and get a byte array.
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest("password123".getBytes(StandardCharsets.UTF_8));
String hex = HexFormat.of().formatHex(hash);
System.out.println(hex); // 64-char hex stringCommon Algorithms
JDK supports: MD5 (broken — never for security), SHA-1 (deprecated for security), SHA-256 (standard), SHA-512 (stronger), SHA3-256 (modern). Always use SHA-256 or SHA-512 for new code.
MessageDigest.getInstance("SHA-256"); // recommended
MessageDigest.getInstance("SHA-512"); // stronger
MessageDigest.getInstance("SHA3-256"); // SHA-3 family
// Never: MessageDigest.getInstance("MD5"); // cryptographically brokenConverting Hash to Hex String
The byte array result must be converted to a hex string for storage or comparison. Use HexFormat (Java 17+) or String.format for older versions.
// Java 17+:
String hex = HexFormat.of().formatHex(hash);
// Older Java:
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
String hex = sb.toString();The Salt: Defeating Rainbow Tables
A rainbow table maps common passwords to their hashes. Salting adds a random value to each password before hashing, making rainbow tables useless. Store the salt alongside the hash.
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(salt);
byte[] hash = md.digest("password".getBytes(StandardCharsets.UTF_8));
// Store: Base64.encode(salt) + ":" + Base64.encode(hash)Password Hashing — Use BCrypt Instead
SHA-256 with a salt is better than plain SHA-256 but still fast — an attacker can try billions of guesses per second. Use a slow KDF: BCryptPasswordEncoder (Spring Security) or PBKDF2, Argon2 for passwords.
// Spring Security — proper password hashing:
PasswordEncoder encoder = new BCryptPasswordEncoder(12); // cost factor 12
String hash = encoder.encode("password123");
boolean match = encoder.matches("password123", hash); // trueFile Integrity Checking
Hash a file to detect corruption or tampering. Compare the computed hash to a known-good reference.
MessageDigest md = MessageDigest.getInstance("SHA-256");
try (InputStream is = Files.newInputStream(Path.of("app.jar"))) {
byte[] buf = new byte[8192];
int n;
while ((n = is.read(buf)) > 0) md.update(buf, 0, n);
}
String hash = HexFormat.of().formatHex(md.digest());
System.out.println("SHA-256: " + hash);Comparing Hashes Securely
Use MessageDigest.isEqual() for constant-time comparison to prevent timing attacks. Never use String.equals() for hash comparison.
byte[] expected = computeHash(storedHash);
byte[] actual = computeHash(inputPassword);
boolean match = MessageDigest.isEqual(expected, actual); // constant-timeChaining Updates
Call md.update(bytes) multiple times before md.digest() to hash data that arrives in chunks (streaming).
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update("part1".getBytes());
md.update("part2".getBytes());
byte[] hash = md.digest(); // hash of "part1" + "part2"Encoding Hashes for Storage
Store binary hashes as Base64 (shorter than hex) or hex strings. Base64 uses 43 chars for SHA-256 vs 64 chars for hex. Both are correct — be consistent.
byte[] hash = md.digest(data);
String base64 = Base64.getEncoder().encodeToString(hash); // 44 chars (with padding)
String hex = HexFormat.of().formatHex(hash); // 64 charsDigestInputStream for Streaming
Wrap an InputStream with DigestInputStream to compute the hash while reading — avoids loading the entire file into memory.
MessageDigest md = MessageDigest.getInstance("SHA-256");
try (DigestInputStream dis = new DigestInputStream(Files.newInputStream(path), md)) {
dis.transferTo(OutputStream.nullOutputStream());
}
String hash = HexFormat.of().formatHex(md.digest());Quick Check
Why is SHA-256 with salt still not recommended for password storage?
Recap
Use MessageDigest.getInstance("SHA-256") for data integrity checks. Always salt passwords — but use BCrypt/Argon2 for password storage, not raw SHA. Use constant-time comparison (MessageDigest.isEqual) to prevent timing attacks.
Frequently asked questions
Is the “Cryptographic Hashing with MessageDigest” lesson free?
Yes — the full text of “Cryptographic Hashing with MessageDigest” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “Cryptographic Hashing with MessageDigest”?
Hash passwords with SHA-256, add salt to prevent rainbow table attacks, and compare digests securely. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Cryptographic Hashing with MessageDigest” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Cryptographic Hashing with MessageDigest
- AES Symmetric Encryption
- HMAC-SHA256 for Message Integrity
- JWT: Structure, Creation, and Verification