59

I'm trying to get the SHA256 of a string in Android.

Here is the PHP code that I want to match:

echo bin2hex(mhash(MHASH_SHA256,"asdf")); //outputs "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b" 

Now, in Java, I'm trying to do the following:

 String password="asdf" MessageDigest digest=null; try { digest = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } digest.reset(); try { Log.i("Eamorr",digest.digest(password.getBytes("UTF-8")).toString()); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } 

But this prints out: "a42yzk3axdv3k4yh98g8"

What did I do wrong here?


Solution thanks to erickson:

 Log.i("Eamorr",bin2hex(getHash("asdf"))); public byte[] getHash(String password) { MessageDigest digest=null; try { digest = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } digest.reset(); return digest.digest(password.getBytes()); } static String bin2hex(byte[] data) { return String.format("%0" + (data.length*2) + "X", new BigInteger(1, data)); } 
7
  • 1
    I think your problem may be the getBytes(UTF-8). Try just getBytes(). Commented Aug 23, 2011 at 19:07
  • 5
    Why should anyone ever use getBytes() without specifying the encoding? Commented Aug 23, 2011 at 19:15
  • 5
    @Eamorr: Could you put the solution in an answer instead of the question, please? Commented Aug 23, 2011 at 19:17
  • The code you have as the solution does not work... any help? Commented Mar 14, 2012 at 21:06
  • 1
    A clean answer is written up here: stackoverflow.com/questions/9661008/… Commented Jan 31, 2014 at 7:42

5 Answers 5

35

The PHP function bin2hex means that it takes a string of bytes and encodes it as a hexadecimal number.

In the Java code, you are trying to take a bunch of random bytes and decode them as a string using your platform's default character encoding. That isn't going to work, and if it did, it wouldn't produce the same results.

Here's a quick-and-dirty binary-to-hex conversion for Java:

static String bin2hex(byte[] data) { StringBuilder hex = new StringBuilder(data.length * 2); for (byte b : data) hex.append(String.format("%02x", b & 0xFF)); return hex.toString(); } 

This is quick to write, not necessarily quick to execute. If you are doing a lot of these, you should rewrite the function with a faster implementation.

Sign up to request clarification or add additional context in comments.

5 Comments

Actually, new BigInteger(1, data).toString(16) is all you need in the case of data from a digest function, because it's guaranteed that no nibble will be full of 0s.
@ClassStacker What's the SHA-1 hash of 0x35326b9705d136d0d1b5efa92d440f3171f1b711?
@erickson I'm definitely to be blamed for claiming no nibble would ever be zero anyway, but here you go; according to python it's \x00P\xd5\rv\xc8\x15u\x84*\xf3\x1d\xc3L\x9b\x14{\xedX? and I stand here guilty. Thanks for pointing this out.
@ClassStacker No problem. SHA-1 and SHA-2 hashes, and I assume any cryptographic digest, can produce zero nybbles and bytes, including leading zeros. I didn't expect otherwise, but when you said it was impossible, it didn't take long to verify my assumption.
@erickson That may not be a problem for you and me, but I presume it has the potential to lead to occasional trouble elsewhere. ;)
27

You are along the right lines, but converting the bytes is a little more complicated. This works on my device:

// utility function private static String bytesToHexString(byte[] bytes) { // http://stackoverflow.com/questions/332079 StringBuffer sb = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(0xFF & bytes[i]); if (hex.length() == 1) { sb.append('0'); } sb.append(hex); } return sb.toString(); } // generate a hash String password="asdf"; MessageDigest digest=null; String hash; try { digest = MessageDigest.getInstance("SHA-256"); digest.update(password.getBytes()); hash = bytesToHexString(digest.digest()); Log.i("Eamorr", "result is " + hash); } catch (NoSuchAlgorithmException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } 

Source: bytesToHexString function is from the IOSched project.

1 Comment

Careful: the bytesToHexString function you took from IOSched project returns the String in lower-case format. When chaining it by doing SHA256(SHA256...(SHA256(input)...) you would get different results from implementations that return the String in upper-case format. This can easily be addressed by chainging the responsible line to String hex = Integer.toHexString(0xFF & bytes[i]).toUpperCase();
9

Complete answer with use example, thanks to erickson.

public static String getSha256Hash(String password) { try { MessageDigest digest = null; try { digest = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } digest.reset(); return bin2hex(digest.digest(password.getBytes())); } catch (Exception ignored) { return null; } } private static String bin2hex(byte[] data) { StringBuilder hex = new StringBuilder(data.length * 2); for (byte b : data) hex.append(String.format("%02x", b & 0xFF)); return hex.toString(); } 

Example of use:

Toast.makeText(this, Utils.getSha256Hash("123456_MY_PASSWORD"), Toast.LENGTH_SHORT).show(); 

Comments

2
private fun stringToSha256(input: String): String { val bytes = input.toByteArray() val md = MessageDigest.getInstance("SHA-256") val digest = md.digest(bytes) // Convert the byte array to a hexadecimal string val result = StringBuilder() for (byte in digest) { result.append(String.format("%02x", byte)) } return result.toString() } 

Comments

1

i know this has been answered but i found a Hashing Library at android arsenal and its very easy,simple and just one line of code. can hash MD5, SHA-1, SHA-256, SHA-384, or SHA-512.

  1. first add this to your gradle and sync

    implementation 'com.github.1AboveAll:Hasher:1.2'

  2. start hasing

    Hasher.Companion.hash("Hello",HashType.SHA_1);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.