In cryptography, MD5 (Message Digest version 5) and SHA (Secure Hash Algorithm) are two well-known message digest algorithms. They are also referred as cryptographic hash functions, which take arbitrary-sized data as input (message) and produce a fixed-length hash value. One of the most important properties of hash functions is, it’s infeasible to generate a message that has a given hash (secure one-way). Hash functions are frequently used to check data integrity such as checking integrity of a downloaded file against its publicly-known hash value. Another common usage is to encrypt user’s password in database.
The Java platform provides two implementation of hashing functions: MD5 (produces 128-bit hash value), SHA-1 (160-bit) and SHA-2 (256-bit). This tutorial demonstrates how to generate MD5 and SHA hash values from String or file using Java.
Here are general steps to generate a hash value from an input (message):
- First approach (suitable for small-sized message):
12345678
// algorithm can be "MD5", "SHA-1", "SHA-256"
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte
[] inputBytes =
// get bytes array from message
byte
[] hashBytes = digest.digest(inputBytes);
// convert hash bytes to string (usually in hexadecimal form)
- Second approach (suitable for large-size message, i.e. large file):
123456789
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte
[] inputBytes =
// get bytes array from message
digest.update(inputBytes);
byte
[] hashedBytes = digest.digest();
// convert hash bytes to string (usually in hexadecimal form)
Now, let’s see some examples in details.
1. Generating Hash from String
The following method takes a message and algorithm name as inputs and returns hexadecimal form of the calculated hash value:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
private static String hashString(String message, String algorithm) throws HashGenerationException { try { MessageDigest digest = MessageDigest.getInstance(algorithm); byte [] hashedBytes = digest.digest(message.getBytes( "UTF-8" )); return convertByteArrayToHexString(hashedBytes); } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) { throw new HashGenerationException( "Could not generate hash from String" , ex); } } |
The HashGenerationException is a custom exception (you can find this class in the attachment). TheconvertByteArrayToHexString() method is implemented as follows:
1
2
3
4
5
6
7
8
|
private static String convertByteArrayToHexString( byte [] arrayBytes) { StringBuffer stringBuffer = new StringBuffer(); for ( int i = 0 ; i < arrayBytes.length; i++) { stringBuffer.append(Integer.toString((arrayBytes[i] & 0xff ) + 0x100 , 16 ) .substring( 1 )); } return stringBuffer.toString(); } |
The hashString() is a general method. Here are four public utility methods that are specific to each algorithm (MD5, SHA-1 and SHA-256):
1
2
3
4
5
6
7
8
9
10
11
|
public static String generateMD5(String message) throws HashGenerationException { return hashString(message, "MD5" ); } public static String generateSHA1(String message) throws HashGenerationException { return hashString(message, "SHA-1" ); } public static String generateSHA256(String message) throws HashGenerationException { return hashString(message, "SHA-256" ); } |
Hence we have the following utility class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package net.codejava.security; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Hash functions utility class. * @author www.codejava.net * */ public class HashGeneratorUtils { private HashGeneratorUtils() { } public static String generateMD5(String message) throws HashGenerationException { return hashString(message, "MD5" ); } public static String generateSHA1(String message) throws HashGenerationException { return hashString(message, "SHA-1" ); } public static String generateSHA256(String message) throws HashGenerationException { return hashString(message, "SHA-256" ); } private static String hashString(String message, String algorithm) throws HashGenerationException { try { MessageDigest digest = MessageDigest.getInstance(algorithm); byte [] hashedBytes = digest.digest(message.getBytes( "UTF-8" )); return convertByteArrayToHexString(hashedBytes); } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) { throw new HashGenerationException( "Could not generate hash from String" , ex); } } private static String convertByteArrayToHexString( byte [] arrayBytes) { StringBuffer stringBuffer = new StringBuffer(); for ( int i = 0 ; i < arrayBytes.length; i++) { stringBuffer.append(Integer.toString((arrayBytes[i] & 0xff ) + 0x100 , 16 ) .substring( 1 )); } return stringBuffer.toString(); } } |
Here’s a test program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package net.codejava.security; /** * Test generating hash values from String. * @author www.codejava.net * */ public class StringHashGeneratorExample { public static void main(String[] args) { try { String inputString = args[ 0 ]; System.out.println( "Input String: " + inputString); String md5Hash = HashGeneratorUtils.generateMD5(inputString); System.out.println( "MD5 Hash: " + md5Hash); String sha1Hash = HashGeneratorUtils.generateSHA1(inputString); System.out.println( "SHA-1 Hash: " + sha1Hash); String sha256Hash = HashGeneratorUtils.generateSHA256(inputString); System.out.println( "SHA-256 Hash: " + sha256Hash); } catch (HashGenerationException ex) { ex.printStackTrace(); } } } |
If the input message is “admin” the test program produces the following output:
1
2
3
4
|
Input String: admin MD5 Hash: 21232f297a57a5a743894a0e4a801fc3 SHA-1 Hash: d033e22ae348aeb5660fc2140aec35850c4da997 SHA-256 Hash: 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 |
2. Generating Hash from File
To calculate hash value of a large file effectively, it’s recommended to repeatedly put a chunk of bytes to the message digest, until reaching end of file. Here’s such method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
private static String hashFile(File file, String algorithm) throws HashGenerationException { try { MessageDigest digest = MessageDigest.getInstance(algorithm); FileInputStream inputStream = new FileInputStream(file); byte [] bytesBuffer = new byte [ 1024 ]; int bytesRead = - 1 ; while ((bytesRead = inputStream.read(bytesBuffer)) != - 1 ) { digest.update(bytesBuffer, 0 , bytesRead); } inputStream.close(); byte [] hashedBytes = digest.digest(); return convertByteArrayToHexString(hashedBytes); } catch (NoSuchAlgorithmException | IOException ex) { throw new HashGenerationException( "Could not generate hash from file" , ex); } } |
Here are four public methods that are specific to each algorithm:
1
2
3
4
5
6
7
8
9
10
11
|
public static String generateMD5(File file) throws HashGenerationException { return hashFile(file, "MD5" ); } public static String generateSHA1(File file) throws HashGenerationException { return hashFile(file, "SHA-1" ); } public static String generateSHA256(File file) throws HashGenerationException { return hashFile(file, "SHA-256" ); } |
And here’s a test program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package net.codejava.security; import java.io.File; /** * Test generating hash values from File. * @author www.codejava.net * */ public class FileHashGeneratorExample { public static void main(String[] args) { try { String filePath = args[ 0 ]; System.out.println( "File Path: " + filePath); File file = new File(filePath); String md5Hash = HashGeneratorUtils.generateMD5(file); System.out.println( "MD5 Hash: " + md5Hash); String sha1Hash = HashGeneratorUtils.generateSHA1(file); System.out.println( "SHA-1 Hash: " + sha1Hash); String sha256Hash = HashGeneratorUtils.generateSHA256(file); System.out.println( "SHA-256 Hash: " + sha256Hash); } catch (HashGenerationException ex) { ex.printStackTrace(); } } } |
Example output:
1
2
3
4
|
File Path: D:JavaPDFViewerJPedalPDFViewer.zip MD5 Hash: 56a86f56a18b73353e5f0afa7b142ed1 SHA- 1 Hash: dc55bd7e84c4787242499ec068fa145bcca01937 SHA- 256 Hash: 093059d79d009662a0a7f70c74cec934a73c1becc8ac813cdcc4995f2aeb882c |
http://www.dzone.com/links/how_to_calculate_md5_and_sha_hash_values_in_java.html