This question already has answers here:
What does value & 0xff do in Java?
(4 answers)
Closed 9 years ago.
With Java, I am converting a String value to a hash using SHA1 on a MessageDigest instance. I am at the point where I have created a hash object:
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] hash = md.digest(password.getBytes("UTF-8"));
The part I do not understand is what b & 0xff means in the following code:
StringBuilder sb = new StringBuilder(2*hash.length);
for(byte b : hash) {
sb.append(String.format("%02x", b & 0xff));
}
I know that %02x means to specify a format where there are two characters using hexadecimal, but I've no idea what the second parameter is, what it does to each byte or what it means. A simple explanation would be great! :-)
That's the bitwise AND operator. b & 0xff gets the last byte of b. Since b is already a byte, I don't see any point to this: the result of the String.format is the same.
Related
This question already has answers here:
How to convert a Binary String to a base 10 integer in Java
(12 answers)
Closed 6 years ago.
I have attempted convert from 10000101 to -123 by code
byte sum = (byte) (Integer.valueOf(10000101, 2) & 0xffff) ";
now I don't know how to convert back from -123 to 10000101.
Any suggestions about using java API to do conversion?
Expanding a bit the David Wallace comment, you can do it with this code:
String fromByteToString = String.format("%8s", Integer.toBinaryString(sum & 0xFF)).replace(' ', '0');
System.out.println(fromByteToString);
with sum & 0xFF you do the bitwise AND operation:
-123 = 11111111111111111111111110000101
0xFF = 00000000000000000000000011111111
res. = 00000000000000000000000010000101
Note that the replace(' ', '0') is not a must in this case because the binary result string starts (10000101) with 1.
This question already has answers here:
java bit manipulation
(5 answers)
Closed 8 years ago.
I have this code:
int i = 255;
byte b = (byte) i;
int c;
System.out.println(Integer.toBinaryString( i));
System.out.println("b = " + b); // b = -1
c=b>>>1;
System.out.println(Integer.toBinaryString( c));
System.out.println(c);
But I can't understand how it works. I think that unsigned shifting to 255(11111111) should give me 127(0111111) but it doesn't. Is my assumption wrong?
Shift operators including >>> operate on ints. The value of b, which is -1 because byte is signed, is promoted to int before the shift. That is why you see the results that you see.
The reason why 255 is re-interpreted as -1 is that 255 has all its eight bits set to one. When you assign that to a signed 8-bit type of byte, it is interpreted as -1 following two's complement rules.
this is how you can get the expected result
c = (0xFF & b) >>> 1;
see dasblinkenlight's answer for details
Try this, and you will understand:
System.out.println(Integer.toBinaryString(i)); // 11111111
System.out.println(Integer.toBinaryString(b)); // 11111111111111111111111111111111
System.out.println(Integer.toBinaryString(c)); // 1111111111111111111111111111111
Variable int i equals 255, so the first print makes sense.
Variable byte b equals -1, because you store 255 in a single byte.
But when you call Integer.toBinaryString(b), the compiler converts b from byte to int, and (int)-1 == FFFFFFFFh == 11111111111111111111111111111111b, hence the second print.
Variable int c equals b>>>1, so the third print makes sense.
This question already has answers here:
how to convert short array to byte array
(3 answers)
Closed 9 years ago.
I am working with audio, I saved audio data on short array. I want to convert it to a byte array to store the wav file. I don't know convert short[] to byte[]. Can you help me.
Thank you very much.
short is 16 bit type and byte is 8 bit type . So from a n length short array you will get a 2n length byte array.
The Basics
before converting an array thing about converting a single short to byte. so as per above line you will create 2 byte from a single short.
The principle will be store first 8 bits two a byte and store second 8 bits to another short. The code will be like this
byte b1, b2;
short s;
b1 = s & 0xff;
b2 = (s >> 8) & 0xff;
Now Array
use the above principal for array now. say the array size of short is n. let the short is s
byte result[2*n];
for(int i = 0; i<2*n ; i=i+2){
b[i] = s[i>>1] & 0xff;
b[i+1] = (s[i>>1 | 1] >> 8) & 0xff;
}
Using ByteBuffer class
you can also convert short array to bytearray using ByteBuffer class.
ByteBuffer byteBuf = ByteBuffer.allocate(2*n);
for(int i = 0; i<n ; i++) {
byteBuf.putShort(buffer[i]);
}
The only way is to create a byte array of the same size as the short array and copy the short array elements
The following code snippet, sourced from Core Java Vol 2 (7th Ed), shows how to create an SHA1 and an MD5 fingerprint using Java.
It turns out that the only function that works is when I load the cleartext from a textfile.
How does MessageDigestFrame.computeDigest() work out the fingerprint, and, particularly the use of the bit shifting pattern (Line 171 - 172)?
public void computeDigest(byte[] b)
{
currentAlgorithm.reset();
currentAlgorithm.update(b);
byte[] hash = currentAlgorithm.digest();
String d = "";
for (int i = 0; i < hash.length; i++)
{
int v = hash[i] & 0xFF;
if (v < 16) d += "0";
d += Integer.toString(v, 16).toUpperCase() + " ";
}
digest.setText(d);
}
The method should work fine whatever you give it - if you're getting the wrong results, I suspect you're loading the file incorrectly. Please show that code, and we can help you work out what's going wrong.
In terms of the code, this line:
int v = hash[i] & 0xFF;
is basically used to treat a byte as unsigned. Bytes are signed in Java - an acknowledged design mistake in the language - but we want to print out the hex value as if it were an unsigned integer. The bitwise AND with just the bottom 8 bits effectively converts it to the integer value of the byte treated as unsigned.
(There are better ways to convert a byte array to a hex string, but that's a separate matter.)
It is not bit shifting, it is bit masking. hash[i] is a byte. When it is widened to integer you need to mask off the higher integer bits because of possible sign extension.
byte b = (byte)0xEF;
System.out.println("No masking: " + (int)b);
System.out.println("Masking: " + (int)(b & 0xFF));
This snipped:
int v = hash[i] & 0xFF;
if (v < 16) d += "0";
d += Integer.toString(v, 16).toUpperCase() + " ";
First you set all but the lowest 8 bits of v to 0 (because 0xFF is 11111111 in binary).
Then if the resulting number is only one digit in hex (< 16) you add a leading "0".
Finally convert the result to hex and add it to the string.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Convert a string representation of a hex dump to a byte array using Java?
For example, I have a string "DEADBEEF". How can I convert it to byte[] bytes = { 0xDE, 0xAD, 0xBE, 0xEF } ?
Loop through each pair of two characters and convert each pair individually:
byte[] bytes = new byte[str.length()/2];
for( int i = 0; i < str.length(); i+=2 )
bytes[i/2] = ((byte)Character.digit(str.charAt(i),16))<<4)+(byte)Character.digit(str.charAt(i),16);
I haven't tested this code out (I don't have a compiler with me atm) but I hope I got the idea through. The subtraction/addition simply converts 'A' into the number 10, 'B' into 11, etc. The bitshifting <<4 moves the first hex digit to the correct place.
EDIT: After rethinking it a bit, I'm not sure if you're asking the correct question. Do you want to convert "DE" into {0xDE}, or perhaps into {0x44,0x45} ? The latter is more useful, the former is more like a homework problem type question.
getBytes() would get you the bytes of the characters in the platform encoding. However it sounds like you want to convert a String containing a Hex representation of bytes into the actual represented byte array.
In which case I would point you toward this existing question: Convert a string representation of a hex dump to a byte array using Java? (note: I personally prefer the 2nd answer to use commons-codec but more out of philosophical reasons)
You can parse the string to a long and then extract the bytes:
String s = "DEADBEEF";
long n = Long.decode( "0x" + s ); //note the use of auto(un)boxing here, for Java 1.4 or below, use Long.decode( "0x" + s ).longValue();
byte[] b = new byte[4];
b[0] = (byte)(n >> 24);
b[1] = (byte)(n >> 16);
b[2] = (byte)(n >> 8);
b[3] = (byte)n;
tskuzzy's answer might be right (didn't test) but if you can, I'd recommend using Commons Codec from Apache. It has a Hex class that does what you need.