By looking around here as well as the internet in general, I have found Bouncy Castle. I want to use Bouncy Castle (or some other freely available utility) to generate a SHA-256 Hash of a String in Java. Looking at their documentation I can't seem to find any good examples of what I want to do. Can anybody here help me out?
-
Here is a comparison of several different SHA256 hash implementations in Java with [example code](https://gist.github.com/scoroberts/a60d61a2cc3afba1e8813b338ecd1501): https://stackoverflow.com/questions/58404400/what-is-the-fastest-way-to-sha-256-encode-many-short-string-values-in-java-on-a – Scott Apr 08 '22 at 22:50
9 Answers
To hash a string, use the built-in MessageDigest class:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.nio.charset.StandardCharsets;
import java.math.BigInteger;
public class CryptoHash {
public static void main(String[] args) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "Text to hash, cryptographically.";
// Change this to UTF-16 if needed
md.update(text.getBytes(StandardCharsets.UTF_8));
byte[] digest = md.digest();
String hex = String.format("%064x", new BigInteger(1, digest));
System.out.println(hex);
}
}
In the snippet above, digest
contains the hashed string and hex
contains a hexadecimal ASCII string with left zero padding.

- 53,280
- 21
- 146
- 188
-
For the same plaintext, does the hash suppose to be different every time? Because that is what happening to me – Thang Pham Aug 09 '10 at 21:06
-
2@Harry Pham, the hash should always be the same, but without more information it would be hard to say why you are getting different ones. You should probably open a new question. – Brendan Long Aug 09 '10 at 21:16
-
2@Harry Pham: After calling `digest` the internal state is reset; so when you call it again without updating before, you get the hash of the empty string. – Debilski Aug 14 '10 at 12:35
-
3
-
1@Sajjad Use your favorite base64 encoding function. I like the one in [Apache Commons](https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/binary/Base64.html) personally. – Brendan Long Oct 22 '13 at 19:34
-
1@Adam No, this is misleading. Calling ´toString´ on a byte array is producing a different result than converting the content of the byte array to String, Brendan Longs answer is more appropriate – Habizzle Feb 04 '15 at 10:15
-
1Java 8 has `Base64.getEncoder()`. See https://stackoverflow.com/a/43294412/548473 – Grigory Kislin Aug 18 '17 at 13:14
-
1I used this method, and while it works nicely because of the String format and its zero paddings, I would suggest using `String hex = Hex.encodeHexString(digest);` from `org.apache.commons.codec.binary.Hex`. You don't need to use own String formats. – RichieRock Jun 11 '20 at 10:46
-
This is already implemented in the runtime libs.
public static String calc(InputStream is) {
String output;
int read;
byte[] buffer = new byte[8192];
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
while ((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] hash = digest.digest();
BigInteger bigInt = new BigInteger(1, hash);
output = bigInt.toString(16);
while ( output.length() < 32 ) {
output = "0"+output;
}
}
catch (Exception e) {
e.printStackTrace(System.err);
return null;
}
return output;
}
In a JEE6+ environment one could also use JAXB DataTypeConverter:
import javax.xml.bind.DatatypeConverter;
String hash = DatatypeConverter.printHexBinary(
MessageDigest.getInstance("MD5").digest("SOMESTRING".getBytes("UTF-8")));

- 68,052
- 28
- 140
- 210
-
3this version has a bug (at least as of today and with java8@win7). try to hash '1234'. the result must start with '03ac67...' but it actually starts with '3ac67...' – Chris Sep 04 '14 at 09:31
-
@Chris thanks, I fixed this here, but I found a better solution my favorite on this is currently: http://stackoverflow.com/questions/415953/how-can-i-generate-an-md5-hash/23273249#23273249 – stacker Sep 04 '14 at 10:47
-
1For new readers of this old thread: The favorite (MD5-hash) referred to by @stacker is now considered insecure (http://en.wikipedia.org/wiki/MD5). – mortensi Dec 17 '14 at 11:15
-
1
-
How we can compare two different hashed value created using same salt? Assume, one come from form login (need to hashed using Salt before compare) and another comes from db and then how we can compare these two? – PAA Dec 29 '15 at 20:40
You don't necessarily need the BouncyCastle library. The following code shows how to do so using the Integer.toHexString function
public static String sha256(String base) {
try{
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(base.getBytes("UTF-8"));
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if(hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch(Exception ex){
throw new RuntimeException(ex);
}
}
Special thanks to user1452273 from this post: How to hash some string with sha256 in Java?
Keep up the good work !
When using hashcodes with any jce provider you first try to get an instance of the algorithm, then update it with the data you want to be hashed and when you are finished you call digest to get the hash value.
MessageDigest sha = MessageDigest.getInstance("SHA-256");
sha.update(in.getBytes());
byte[] digest = sha.digest();
you can use the digest to get a base64 or hex encoded version according to your needs

- 18,045
- 16
- 68
- 92

- 19,708
- 3
- 45
- 61
-
Out of curiosity, can you go straight to `digest()` with the input byte array, skipping `update()`? – ladenedge Jun 23 '10 at 16:56
-
One thing I noticed is that this works with "SHA-256" whereas "SHA256" throws a NoSuchAlgorithmException. No biggie. – knpwrs Jun 23 '10 at 16:58
-
9As per my comment to Brandon, **do not** use `String.getBytes()` without specifying an encoding. Currently this code can give different results on different platforms - which is broken behaviour for a well-defined hash. – Jon Skeet Jun 23 '10 at 17:06
-
@ladenedge yes - if your string is short enought @KPthunder your right @Jon Skeet depends on the content of the string - but yes add an encoding string getBytes to be on the save side – Nikolaus Gradwohl Jun 23 '10 at 17:15
Java 8: Base64 available:
MessageDigest md = MessageDigest.getInstance( "SHA-512" );
md.update( inbytes );
byte[] aMessageDigest = md.digest();
String outEncoded = Base64.getEncoder().encodeToString( aMessageDigest );
return( outEncoded );

- 121
- 1
- 1
I suppose you are using a relatively old Java Version without SHA-256. So you must add the BouncyCastle Provider to the already provided 'Security Providers' in your java version.
// NEEDED if you are using a Java version without SHA-256
Security.addProvider(new BouncyCastleProvider());
// then go as usual
MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "my string...";
md.update(text.getBytes("UTF-8")); // or UTF-16 if needed
byte[] digest = md.digest();

- 1,743
- 15
- 23
-
+1 for mentioning BouncyCastle, which adds quite a few new MessageDigests compared to the relatively paltry selection available in the JDK. – mjuarez Jul 27 '14 at 09:51
-
4Without package/provider info the "Hex" class is not very helpful. And if that is Hex from Apache Commons Codec I would use `return Hex.encodeHexString(digest)` instead. – eckes Nov 15 '13 at 01:40
Using Java 8
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
String encoded = DatatypeConverter.printHexBinary(hash);
System.out.println(encoded.toLowerCase());

- 2,402
- 1
- 21
- 40
This will work with "org.bouncycastle.util.encoders.Hex" following package
return new String(Hex.encode(digest));
Its in bouncycastle jar.

- 45
- 1
- 8