3

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?

4
  • Please read faq before posting. Commented Apr 27, 2013 at 16:29
  • @Nikhil: What's wrong with this post? Commented Apr 27, 2013 at 16:30
  • @pino copying code and asking here. Can't he refer official documents first. and show hhat he studied.is efforts t Commented Apr 27, 2013 at 16:33
  • @Nikhil: I don't agree. What official document could answer his question? Copying someone else's code is not discouraged by the FAQ, on the contrary FAQ says "We feel the best Stack Overflow questions have a bit of source code in them". He has a problem with a software algorithm he cannot understand: it's perfectly in-topic. Commented Apr 27, 2013 at 17:04

2 Answers 2

6

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);
Sign up to request clarification or add additional context in comments.

Comments

1

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.

2 Comments

"just in case byte is more than 8 bits" sounds very bad.
True. I never like to make assumptions about the underlying hardware, but in this case, the Java spec seems to say that a byte can never be more than 8 bits, so I've simplified my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.