Java: SHA-256 hashing for integrity
Compute a SHA-256 digest with MessageDigest and see that a tiny change produces a completely different value.
On this page
Java strings, bytes, and exceptions.
- Compute a SHA-256 digest with MessageDigest and see that a tiny change produces a completely different value.
- Predict the sample output and explain the state changes.
- Complete the practice task and check the boundary cases.
The concept
A cryptographic hash function turns any input into a fixed-size digest. It is deterministic, one-way, and designed so that a tiny change in the input changes the digest unpredictably. SHA-256 produces 32 bytes, shown here as 64 hexadecimal characters.
Hashes are used to check integrity: if a downloaded file's digest matches the published one, the file was not corrupted or altered. MessageDigest.isEqual compares two byte arrays in constant time, which avoids leaking how many leading bytes matched. A plain fast hash is not suitable for storing passwords.
Code example
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
class Main {
static String hex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
MessageDigest sha = MessageDigest.getInstance("SHA-256");
String a = hex(sha.digest("abc".getBytes(StandardCharsets.UTF_8)));
String b = hex(sha.digest("abd".getBytes(StandardCharsets.UTF_8)));
System.out.println(a);
System.out.println(b);
System.out.println(MessageDigest.isEqual(a.getBytes(StandardCharsets.UTF_8), a.getBytes(StandardCharsets.UTF_8)));
}
}ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad a52d159f262b2c6ddb724a61840befc36eb30c88877a4030b65cbe86298449c9 true
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
import java.nio.charset.StandardCharsets;import java.security.MessageDigest; class Main { static String hex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } public static void main(String[] args) throws Exception { MessageDigest sha = MessageDigest.getInstance("SHA-256"); String a = hex(sha.digest("abc".getBytes(StandardCharsets.UTF_8))); String b = hex(sha.digest("abd".getBytes(StandardCharsets.UTF_8))); System.out.println(a); System.out.println(b); System.out.println(MessageDigest.isEqual(a.getBytes(StandardCharsets.UTF_8), a.getBytes(StandardCharsets.UTF_8))); }}Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| Create a SHA-256 digest engine. | — | — | |
| Hash the bytes of abc. This is a standard SHA-256 test vector. | 32 bytes → 64 hex characters | — | |
| Print the digest of abc. | 32 bytes → 64 hex characters | ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad | |
| Changing one letter produces a completely different digest. | 32 bytes → 64 hex characters | ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad a52d159f262b2c6ddb724a61840befc36eb30c88877a4030b65cbe86298449c9 | |
| A constant-time comparison of equal values returns true. | 32 bytes → 64 hex characters | ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad a52d159f262b2c6ddb724a61840befc36eb30c88877a4030b65cbe86298449c9 true |
Behind the scenes
How Java processes this code
The Java compiler produces bytecode. The JVM loads the class and invokes its main method.
Cost and common mistakes
O(m) time for an m-byte input and a fixed 32-byte output.
- Always convert text to bytes with an explicit charset such as UTF-8, otherwise the digest depends on the platform default.
- Plain SHA-256 is fast, which helps attackers who guess passwords. Use a slow, salted password hash for passwords.
- MD5 and SHA-1 are broken for collision resistance and must not be used for new security work.
Try it yourself
How can you check a downloaded file against a published digest?
Reveal answer and reasoning
Hash the file's bytes with the same algorithm and compare the hex result with the published value; they must match exactly.