Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange algorithm to convert binary SHA-1 digest to hex string

in the Internet I found this code to generate a SHA1 hash:

        public static String hash(String str) {
            try {
                    MessageDigest mg = MessageDigest.getInstance("SHA-1");
                    byte[] result = mg.digest(str.getBytes());
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i < result.length; i++) {
                            sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
                    }
                    return sb.toString();
            } catch (NoSuchAlgorithmException e) {
                    System.err.println("SHA-1 not found.");
                    return "";
            }
    }

But why is there (result[i] & 0xff) + 0x100?

like image 269
criztovyl Avatar asked Dec 02 '25 10:12

criztovyl


2 Answers

Bytes are signed: they could be negative. When a negative byte is handled by Integer.toString() generates a string beginning with "FFFFFF", but this doesn't happen with positive bytes, so the length of the resulting string is not fixed. The & 0xff converts the byte to an unsigned integer. Then 0x100 is added to ensure that the hex string is 3 chars long; this is needed because we want a string with 2 hex digits for each byte but a byte between 0 and 15 would produce 1 char only. Finally the third digit is discarded with substring(1).

I suggest to substitute StringBuffer with StringBuilder because it is slightly more efficient and also to specify the initial buffer length:

StringBuilder sb = new StringBuilder(result.length * 2);
like image 91
Pino Avatar answered Dec 05 '25 00:12

Pino


The & 0xff is there just in case byte gets promoted to something larger than 8 bits and sign-extended.

Sign-extension is a very real problem here, so the 0xff is needed for that reason at the very least.

like image 20
Edward Falk Avatar answered Dec 04 '25 23:12

Edward Falk