Can't seem to generate hex-encoded string from SHA256 digest in Java
Can't seem to figure out where Im going wrong here:
private static String generateHashFromFile(String filePath) {
try {
final int BUFSZ = 32768;
MessageDigest sha = MessageDigest.getInstance("SHA-256");
FileInputStream in = new FileInputStream(filePath);
BufferedInputStream is = new BufferedInputStream(in, BUFSZ);
byte[] buffer = new byte[BUFSZ];
int num = -1;
while((num = is.read(buffer)) != -1) {
sha.update(buffer, 0, num);
}
is.close();
byte[] hash = sha.digest();
return byteArrayToHex(hash);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private static String byteArrayToHex(byte[] barray)
{
char[] c = ne开发者_Go百科w char[barray.length * 2];
byte b;
for (int i = 0; i < barray.length; ++i)
{
b = ((byte)(barray[i] >> 4));
c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
b = ((byte)(barray[i] & 0xF));
c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
}
return new String(c);
}
Im getting strings like:
")469.76F5941+31E25)6,9,C26)978)4*917180A4C(B7C,E,D+6,7133C705167"
Clearly not hexadecimal!
Questions:
- Is the hash generation code correct?
- Is the hex encoding method correct?
- Am I missing something with regards to encoding?
Your hash generation code is correct. To convert byte[] barray
into a hex string, you can simply do:
String c = new String();
for(short i = 0; i < barray.length; i++) {
c += Integer.toString((barray[i] & 255) + 256, 16).substring(1).toUpperCase();
}
Both your hash generation and hex encoding code works. I would take a closer look at the contents of the file you're reading.
You can also write your hex encoding method like so:
public static String byteArrayToHex(byte[] barray) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < barray.length; i++) {
String hex = Integer.toHexString(0xff & barray[i]);
if (hex.length() == 1) sb.append('0');
sb.append(hex);
}
return sb.toString();
}
A byte
value is signed, and you are using the signed-preserving right-shift. This will result in negative values for b
when computing the high-order nybble.
For example, consider what your code does with a byte
value -112 (0x90). When right-shifting, it is first promoted to an int
value, 0xFFFFFF90. Then it is shifted right 4 bits, preserving the sign, and becomes 0xFFFFFFF9. This is then cast back to a byte, which simply discards the high-order 24 bits, and 0xF9 (-7 decimal) is assigned to b
. b
is not greater than 9, so the resulting character is (-7 + 48), or ')'.
Do this instead:
int hi = (barray[i] & 0xF0) >>> 4, lo = barray[i] & 0xF;
The use of a byte
as a local variable doesn't do any good on a 32- or 64-bit machine. In fact, the cast to byte
is a wasted instruction.
精彩评论