0

I am using org.apache.commons.codec.digest.DigestUtils library to calculate the SHA1 hash in Java. DigestUtils.sha1Hex("0x808204E039EFB76D96D3780BB507674").

Unfortunately, this doesn't give the same result as the below SQL statement?

select HASHBYTES('SHA1', CONVERT(VARBINARY(MAX),
0x808204E039EFB76D96D3780BB507674,1))

The equivalent of varbinary is byte[] in Java. So, I tried DigestUtils.sha1Hex("0x808204E039EFB76D96D3780BB507674".getBytes()) but this didn't help either. Please guide.

1 Answers1

1

Do not use getBytes(). It has nothing to do with decoding hex values.

getBytes() returns one or more bytes for each character in a String, using the underlying system’s default charset. That charset is almost certainly either UTF-8 or windows-125x, which means all the characters in your String will have a single corresponding byte, due to the way those charsets convert characters to and from bytes.

So, your byte array will have values like this, which is definitely not what you want:

{
    56, // codepoint for the '8' character
    48, // codepoint for the '0' character
    56, // codepoint for the '8' character
    50, // codepoint for the '2' character
    48, // codepoint for the '0' character
    52, // codepoint for the '4' character
    69, // codepoint for the 'E' character
    // etc.
}

“Hex” is short for hexadecimal, or base 16. In base 16, two digits represent a byte value—that is, a value from 0 to 2⁸−1. You need to parse every two digits into a single byte value.

While there are third party utilities for this, it’s so easy that you’re really better off doing it manually:

String s = "0x808204E039EFB76D96D3780BB507674";

// chop off "0x"
s = s.substring(2);

byte[] bytes = new BigInteger(s, 16).toByteArray();

Now, the byte array will have values that correspond to the bytes represented by your hex digits:

{
    8,      // 0x8
    8,      // 0x08
    32,     // 0x20
    78,     // 0x4E
    3,      // 0x03
    -98,    // 0x9E
    // etc.
}
VGR
  • 40,506
  • 4
  • 48
  • 63