1

Now I understand java doesn't have unsigned bytes, but I'm not sure how to solve this if not. I'm trying to implement SHA256 hashing in java, and i'm in the processing of converting the message to 512-bit.

int l = bytes.length; //total amount of bytes in the original message
int k = 0;
while((l+1+k) % 512 != 448) {
        k++;
}
//k is the total amount of 0's to be padded
int rest = k % 8;  //get the amount of 0's to be added in the byte with the 1
byte tmp =(byte) Math.pow(2, rest);

So the key instruction is the last row, if rest = 7 the resulting int is 128, but the bytes are signed in java and so the byte becomes 0x80 instead of 0xF0. How can I achieve this in Java?

If anyone has a idea on how to implement this part please let me know.

10
  • 1
    Why would 128 be 0xF0 ? Commented May 17, 2017 at 14:59
  • RIght, rest should be a number from 0 to 7, which are all positive already and fit inside a byte's range. I think you may have another issue. Commented May 17, 2017 at 15:00
  • 4
    Just for the record: this is for learning purposes? You know that implementing your own cryptography is most likely most often a very bad idea in the real world? Commented May 17, 2017 at 15:02
  • 2
    Incidentally, you're better off doing 1<<rest instead of Math.pow(2, rest) Commented May 17, 2017 at 15:02
  • "Java doesn't have unsigned bytes" is not directly wrong, but it usually misses the point. Signed bytes still have 8 bits in them, and you can just (carefully) treat them as unsigned bytes. (byte)128 is still the correct result, even though it looks like -128 in the debugger. It's 0x80 either way. Commented May 17, 2017 at 15:05

1 Answer 1

1

Starting from the assumption your message consists of bytes, the padding always works out as mupltiple of 8 bits, aka bytes. This ensures the most significant pad bit is always located in bit 7 of the first padding byte following the message, thus the padding, if any, is always started by 0x80, follwed by as many 0x00 as needed.

This can be implemented in a very simple manner:

public static byte[] padMsg(byte[] rawMsg) {
    int rawLen = rawMsg.length;
    int padLen = (64 - (rawLen & 0x3F)) & 0x3F;
    if (padLen == 0)
        return rawMsg;
    // all extra bytes in padded msg are zeros.
    byte[] paddedMsg = Arrays.copyOf(rawMsg, rawLen + padLen);
    // ensure topmost pad bit is a one
    paddedMsg[rawLen] = (byte) 0x80;
    return paddedMsg;
}

This takes the message length and gets the remainder. The remainder of a power of two (in this case 64), is most effectively gotten by simply and-masking with (power - 1), and this is where the 0x3F in the code comes from (= 64 - 1). The remainder is taken again after calculating (64 - remainder) as prelimary padding length, to catch the special case where remainder is 0, leading to a wrong padding length of 64 bytes (which should be 0 padding).

Once the padding length in bytes is known, the case padding = 0 is caught. In any other case the message length is increased (with 0x00 bytes, Arrays.copyOf does this automatically). Then the first padding byte is replaced with 0x80 and the padded message that is now guaranteed to be a multiple of 64 bytes long is returned.

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

Comments

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.