Main Tutorials

Java SHA-256 and SHA3-256 Hashing Example

In Java, we can use MessageDigest to get a SHA-256 or SHA3-256 hashing algorithm to hash a string.


  MessageDigest md = MessageDigest.getInstance("SHA3-256");
  byte[] result = md.digest(input);

This article shows how to use Java SHA-256 and SHA3-256 algorithms to generate a hash value from a given string and checksum from a file.

Note
The hashing is a one-way compression function to convert inputs of different lengths into a fixed-length output (hash value).

1. SHA-2 and SHA-3

1.1 The SHA-2 (Secure Hash Algorithm 2) is defined in FIPS PUB 180-4. The SHA-2 is a widely used hashing algorithm designed by the National Security Agency (NSA).

Java supports the following SHA-2 algorithms:

  • SHA-224
  • SHA-256
  • SHA-384
  • SHA-512
  • SHA-512/224
  • SHA-512/256

The SHA-256 produces a 256-bit output, 32 bytes, while SHA-512 produces a 512-bit output, 64 bytes.


String : Hello World

SHA-256
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e

SHA-512
2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b

1.2 The SHA-3 (Secure Hash Algorithm 3) is defined in FIPS PUB 202. The SHA-3 is the latest member of the Secure Hash Algorithms, released by National Institute of Standards and Technology (NIST).

Java supports the following SHA-3 algorithms:

  • SHA3-224
  • SHA3-256
  • SHA3-384
  • SHA3-512

String : Hello World

SHA3-256
e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51

SHA3-512
2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b

2. Java SHA3-256 Hashing

This Java example hashes a string with the SHA3-256 algorithm.

ShaUtils.java

package com.mkyong.crypto.hash;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class ShaUtils {

    private static final Charset UTF_8 = StandardCharsets.UTF_8;
    private static final String OUTPUT_FORMAT = "%-20s:%s";

    public static byte[] digest(byte[] input, String algorithm) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException(e);
        }
        byte[] result = md.digest(input);
        return result;
    }

    public static String bytesToHex(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) {

        //String algorithm = "SHA-256"; // if you perfer SHA-2
        String algorithm = "SHA3-256";

        String pText = "Hello World";
        System.out.println(String.format(OUTPUT_FORMAT, "Input (string)", pText));
        System.out.println(String.format(OUTPUT_FORMAT, "Input (length)", pText.length()));

        byte[] shaInBytes = ShaUtils.digest(pText.getBytes(UTF_8), algorithm);
        System.out.println(String.format(OUTPUT_FORMAT, algorithm + " (hex) ", bytesToHex(shaInBytes)));
        // fixed length, 32 bytes, 256 bits.
        System.out.println(String.format(OUTPUT_FORMAT, algorithm + " (length)", shaInBytes.length));


    }
}

Output


Input (string)      :Hello World
Input (length)      :11
SHA3-256 (hex)      :e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51
SHA3-256 (length)   :32

Try hash another string, differ length, for SHA3-256, the output fixed to 256 bits, 32 bytes.

Output


Input (string)      :Hello SHA Hashing
Input (length)      :17
SHA3-256 (hex)      :72fbf4f3a807d344a1ee492ff4183edf72e45fab8dfa6a6e5447226233633bf8
SHA3-256 (length)   :32

3. Java SHA3-256 File Checksum

A file in resources folder.

sha-file.txt

Hello World

This example uses the SHA3-256 algorithm to generate a checksum for the above file.

ShaUtils.java

package com.mkyong.crypto.hash;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class ShaUtils {

    private static byte[] checksum(String filePath, String algorithm) {

        MessageDigest md;
        try {
            md = MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException(e);
        }

        try (InputStream is = new FileInputStream(filePath);
             DigestInputStream dis = new DigestInputStream(is, md)) {
            while (dis.read() != -1) ; //empty loop to clear the data
            md = dis.getMessageDigest();
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
        return md.digest();

    }

    public static String bytesToHex(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) {

        String algorithm = "SHA3-256";

        // get file path from resources
        String filePath = ClassLoader.getSystemResource("sha-file.txt").getFile();

        byte[] hashInBytes = checksum(filePath, algorithm);
        System.out.println(bytesToHex(hashInBytes));


    }
}

Output


e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51

4. NoSuchAlgorithmException

Read this for all Java supported MessageDigest Algorithms. If we provide a non existed algorithm, for example, SHA4-256, Java throws java.security.NoSuchAlgorithmException.


MessageDigest md = MessageDigest.getInstance("SHA4-256");

java.security.NoSuchAlgorithmException: SHA4-256 MessageDigest not available
	at com.mkyong.crypto.hash.ShaUtils.digest(ShaUtils.java:22)
	at com.mkyong.crypto.hash.ShaUtils.main(ShaUtils.java:65)
Caused by: java.security.NoSuchAlgorithmException: SHA4-256 MessageDigest not available
	at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:159)
	at java.base/java.security.Security.getImpl(Security.java:700)
	at java.base/java.security.MessageDigest.getInstance(MessageDigest.java:178)
	at com.mkyong.crypto.hash.ShaUtils.digest(ShaUtils.java:20)
	... 1 more

5. Apache Commons Codec

This example uses the popular Apache Commons Codec to hash a string with the SHA algorithms.

pom.xml

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.14</version>
</dependency>

import org.apache.commons.codec.digest.DigestUtils;

    // SHA-2
    byte[] hash1 = DigestUtils.sha256("");      // returns byte arrays

    String hash2 = DigestUtils.sha256Hex("");   // returns encoded hex

    // SHA-3
    byte[] hash3 = DigestUtils.sha3_256("");     // returns byte arrays

    String hash4 = DigestUtils.sha3_256Hex("");  // returns encoded hex

6. Add Salt to SHA hashing

The salt is a random data, a technique to prevent rainbow attacks. In Java, we can use SecureRandom to generate a salt (random bytes).


  public static byte[] getRandomNonce(int numBytes) {
      byte[] nonce = new byte[numBytes];
      new SecureRandom().nextBytes(nonce);
      return nonce;
  }

This example generates a random 16 bytes salt and uses ByteBuffer to prefix it to a string. In the end, we use the SHA3-256 algorithm to generate a hash value from the salt + string.


  // get a 16 bytes random salt.
  byte[] salt = CryptoUtils.getRandomNonce(16);
  byte[] pText = "Hello World".getBytes(StandardCharsets.UTF_8);

  // combine two byte arrays
  byte[] input = ByteBuffer.allocate(salt.length + pText.length)
          .put(salt)
          .put(pText)
          .array();

  // no salt, SHA3-256
  System.out.println(bytesToHex(ShaUtils.digest(pText, "SHA3-256")));

  // 16 bytes salt, SHA3-256
  System.out.println(bytesToHex(ShaUtils.digest(input, "SHA3-256")));

Output


# no salt
e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51

# 16 bytes salt
a6c589937ea475fc942d31d154d359ff569ff99fa32ee5d996ff64eca2e7551b

Note
For password hashing, we can use Bcrypt or Argon2.

Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-crypto

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
49 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Suraj
6 years ago

How to decrypt SHA-2 256 algorithm??

Pallav Raj
6 years ago

Hi MkYong… I have a question. if anyone can answer please reply to this comment. My question is, I encrypted a password with SHA-256. Now I am logging to my application with my userId and password. Now I have String password and encrypted password. How can I validate my user? Do i need to decrypt my password, if yes, then if possible please provide solution. Thank you in Advance.

Lionel
4 years ago
Reply to  Pallav Raj

This is hashing and not encryption, once you hash something you cannot revert it to its original value.
What you need to do is in the login logic is to hash the password that the user has entered and compared the resulting hash with the one that is stored in the database, if it matches then it is the same password.

Anu
4 years ago
Reply to  Pallav Raj

hi do u got any solution..if yes pls share am in need of it now

Lionel
4 years ago
Reply to  Anu

See my reply above.

pancho
7 years ago

te amo

Ayoub
7 years ago

Hi all,
I found that the hash for the input “hello world!” gives different results .

Hex format : 323b1637c7999942fbebfe5d42fe15dbfe93737577663afa0181938d7ad4a2ac
Hex format : 323b1637c7999942fbebfe5d42fe15dbfe93737577663afa181938d7ad4a2ac

like what @StYleZ said there is a 0(“zero”) missing.

Savani
8 years ago

Hi Mkyong,

How we can compare two hashed values for the same salt ? Please share sample code / links etc.

Regards, Savani

chhorn
1 year ago

thank you for mkyong.com

dannie
2 years ago

Write a program that reads a file containing text and, assuming that most
words are English, guesses whether the encoding is ASCII, ISO 8859-1,
UTF-8, or UTF-16, and if the latter, which byte ordering is used.

Aks1316
5 years ago

I am not able to understand code you have written here. toHexString(0xff & byteData[i]) what this will do ? why 0xff is added?
and why appending 0 when length is 1

Steve Newson
6 years ago

Alternative method for generating the hex string:

javax.xml.bind.DatatypeConverter.printHexBinary(byteData).toLowerCase()

sandeep
6 years ago

can you get the original string from hash code .If not then what is use if Hashing ?

Zoran Davidovi?
7 years ago

“The possible MessageDigest algorithm are SHA-1, SHA-256, SHA-384, and SHA-512, you can check the reference for the detail.” You forgot SHA-224 algorithm.

Guillaume Husta
6 years ago

We can also get the complete list with :
Set algosMessageDigest = Security.getAlgorithms(“MessageDigest”);
😉

Yuriy Tereschuk
9 years ago

@Mkyong, can you update the second reference in References part, because it’s not valid.

diya
9 years ago

how do i generate hash value by passing multiple parameters? If i need to send 2 strings and generate a hash value ..is it possible?

UN-deathx
9 years ago

Thank’s

Zeza
10 years ago

hi all,
i’m very new in programming,
i have urgent task: i have to send message signed by some key
i have an example on Cscharp but i need it written on Java, please help me!
************************************************************************************************************
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text;
using System.Net;
using System.Net.Security;
using System.Globalization;
using System.Security.Policy;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace uwcfs.sample
{
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
string msg = “”;

ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(RemoteCertificateValidationCB);

msg += Environment.NewLine + ” — MoneyTransfer — ” + Environment.NewLine + Environment.NewLine;

msg += GetCurrencyList() + ” – GetCurrencyList ” + Environment.NewLine;
msg += GetComission() + ” – GetComission ” + Environment.NewLine;

MessageBox.Show(msg);
}

public static bool RemoteCertificateValidationCB(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
//For test, accept any certificate
return true;
}

public static string GetCurrencyList()
{
string key = “nA{oYd;aFmewCZ=6(^CT3jsNtRT9Cq}gCVF0i0Yq.#0_3sh05ndK%1hkKpA@D6CI”;

MT.UWCFSMoneyTransferSoapClient ws = new MT.UWCFSMoneyTransferSoapClient();
MT.UWCFSMoneyTransferGetCurrencyListRequest request = new MT.UWCFSMoneyTransferGetCurrencyListRequest();
MT.Signature sign = new MT.Signature();
MT.UWCFSMoneyTransferGetCurrencyListResponse response;

sign.MerchantCode = “FASTER”;
string hashData = key;
sign.Sign = HASH.getHash512(hashData).ToUpper();

response = ws.GetCurrencyList(request, sign);

return (0 == response.Response.ErrorCode) ? “OK” + ” (currencies: ” + response.Currencies.Length.ToString() + “)” : “ERROR. ” + response.Response.ErrorCode.ToString() + response.Response.ErrorMessage;
//return (0 == response.Response.ErrorCode) ? “OK” : “ERROR”;
}

public static string GetComission()
{
string key = “nA{oYd;aFmewCZ=6(^CT3jsNtRT9Cq}gCVF0i0Yq.#0_3sh05ndK%1hkKpA@D6CI”;

MT.UWCFSMoneyTransferSoapClient ws = new MT.UWCFSMoneyTransferSoapClient();
MT.UWCFSMoneyTransferGetComissionRequest request = new MT.UWCFSMoneyTransferGetComissionRequest();
MT.Signature sign = new MT.Signature();
MT.UWCFSMoneyTransferGetComissionResponse response;

request.Amount = 100M;
request.BankID = 673309;
request.ComissionIncluded = 0;
request.CurrencyCode = “USD”;

sign.MerchantCode = “FASTER”;
string hashData = request.BankID.ToString() + request.ComissionIncluded.ToString() + request.CurrencyCode + request.Amount.ToString() + request.UserID.ToString() + request.Discount + key;
sign.Sign = HASH.getHash512(hashData).ToUpper();

response = ws.GetComission(request, sign);

return (0 == response.Response.ErrorCode) ? “OK” + ” (comission: ” + response.TransactionFee.ToString() + “)” : “ERROR. ” + response.Response.ErrorCode.ToString() + response.Response.ErrorMessage;
//return (0 == response.Response.ErrorCode) ? “OK” : “ERROR”;
}
}

public static class HASH
{
public static string getHash512(string data)
{
string hash = “”;

UTF8Encoding enc = new UTF8Encoding();
SHA512Managed sha = new SHA512Managed();
byte[] dataBytes = enc.GetBytes(data);
byte[] hashBytes = sha.ComputeHash(dataBytes);

foreach (byte b in hashBytes)
{
hash += String.Format(“{0:x2}”, b);
}

return hash;
}
}
}
******************************************************************************************************************************

mery
11 years ago

Method 2 gives another result..
A problem by “01”
Hex format : 8a47c4856ca6de2a016f3a2ab10ef79362ecfc73b038bccfa6eff48afcef4244
Hex format : 8a47c4856ca6de2a16f3a2ab1ef79362ecfc73b038bccfa6eff48afcef4244

sheeysong
11 years ago

Hi Yong,
Thanks for this simple toHexString() code block, can you shed your light to reverse it back to the original ascii String in Java? I tried to write a block of code to convert your MessageDigest byte[] back to String (String HexByteToString(byte[] digestByte), but not quite right somehow.
Thanks,

~Jing

Bambat
11 years ago
String digestAlgorithm = "SHA-256";
String fileName = "/tmp/test";
String result;
// Obtain a message digest object.
            MessageDigest md = MessageDigest.getInstance(digestAlgorithm);

            // Calculate the digest for the given file.
            DigestInputStream in = new DigestInputStream(
                    new FileInputStream(fileName), md);
            byte[] buffer = new byte[8192];
            while (0 < in.read(buffer)){}
            // gets digest
            byte[] digest = md.digest();
            // convert the byte to hex format
            StringBuilder sb = new StringBuilder();
            for (byte d : digest) {
                sb.append(String.format("%02x", d));
            }
            result = sb.toString();
Sudhakar
11 years ago

I tried, { 2. Hashing String with SHA-256 } Example.

//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}

When i refresh the page. this code gets looped.
Example:
First Output: 1x2x3x
Second Output: 1x2x3x1x2x3x
Third Output: 1x2x3x1x2x3x1x2x3x

But second one works good.

Daniel Serodio
11 years ago

You forgot to close the FileInputStream in the first example.

BillR
11 years ago

getBytes() is platform dependent. you should specify an encoding so that it works no matter what encoding is used on your platform.

venkateswarlu
11 years ago

what is package com.mkyong.test;

Sudhakar
11 years ago
Reply to  venkateswarlu

com.mkyong.test;

Its your current package or folder.
You are writing your code in com/mkyong/test folder.

Santis
11 years ago

Hi,
Thank you for your article. Second method of converting the byte to hex is more efficient than first one (about 30%).
But I have different problem. When I compared Java SHA-256 hashing with Linux program (echo 123456 | sha256sum) I’ve got different results (for “123456”):
JAVA: 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
LINUX: e150a1ec81e8e93e1eae2c3a77e66ec6dbd6a3b460f89c1d08aecf422ee401a0

I can’t find reason, do you know one?

einsty
11 years ago
Reply to  Santis

Note that you will need to use echo -n 123456 | sha256sum

The echo command includes a carriage return i believe and that is getting hashed as well… that’s the reason your result will be different.

Santis
11 years ago
Reply to  einsty

That’s the point. Thank you.

StYleZ
12 years ago

Hi @ll,

1. File checksum with SHA-256 -> //convert the byte to hex format method 2 = doesn’t work correntcly!

Here my output:
Hex format : da84e5104ec02982515127adda821ffc533acf7f07bd9b5839f31239e888feea
Hex format : da84e5104ec02982515127adda821ffc533acf7f7bd9b5839f31239e888feea

As you may have noticed there is as 0(“zero”) missing.
Methond 1 is fine.

Thx for this Tutorail – it helped me alot!

Greets
StYleZ

ChaZ
10 years ago
Reply to  StYleZ

What was your input?

FixingError
8 years ago
Reply to  ChaZ

The reason that the 2nd method would output wrong because it eats up leading zero of any hex-pair value. For example, a hex value of x07 will be output as 7 in the string. As a result, the 2nd method will output a wrong result for a hex value from x00 to x0F. Hope this help people in the future.

Joe
12 years ago

Thank you so much, this tutorial is very useful and clear.

Bart Oudhoff
12 years ago

Thanks, this helped me out a lot!

Neha
10 years ago
Reply to  Bart Oudhoff

But , this is not helped me a lot!!!!!!!!!!!!!!!!!!!!!!!!

Lucky Luck
12 years ago

Hi,
Can you please tell me that how can we convert the SHA-256 Hash into simple text, using javascript, c#.net?
Thanks

John
12 years ago

why don’t you use DigestInputStream?

Jersey Jim
12 years ago

Another byte to hex format method:

java.math.BigInteger number = new java.math.BigInteger(1, byteData);
System.out.println(String.format("%1$032x", number));

I saw this idea in the comments at: http://www.spiration.co.uk/post/1199/Java-md5-example-with-MessageDigest

Jersey Jim
12 years ago
Reply to  Jersey Jim

-oops should have been:

java.math.BigInteger number = new java.math.BigInteger(1, byteData);
System.out.println(String.format("%1$064x", number));

Sorry about that!

forber
12 years ago

Wrong:(2. Hashing String with SHA-256)
System.out.println(Hex format : ” + hexString.toString());

Right
System.out.println(“Hex format : ” + hexString.toString());

Dipika
10 years ago
Reply to  mkyong

Hi Sir,

Its really a very good job you are doing
Just a suggestion, there is no searching option available on this site.
Could you please add the same.

Rishabh
11 years ago
Reply to  mkyong

Hi Sir,

Its really a very good job you are doing
Just a suggestion, there is no searching option available on this site.
Could you please add the same.