6

TLDR: Java is signed, c# is unsigned. Byte[] values are different, how to solve this. How can I convert either side to the other?

Values are of "Hello World" MD5 hashed and then converted to bytes

Java:

-79, 10, -115, -79, 100, -32, 117, 65, 5, -73, -87, -101, -25, 46, 63, -27

C#:

177, 10, 141, 177, 100, 224, 117, 65, 5, 183, 169, 155, 231, 46, 63, 229

I use the byte[] to encrypt using AES on both sides but the passwords never match.

user5581557
  • 213
  • 4
  • 14
  • http://stackoverflow.com/questions/2920044/how-can-you-generate-the-same-md5-hashcode-in-c-sharp-and-java – Parthasarathy May 24 '16 at 10:47
  • The values aren't different. They're *represented* differently. You can be sure that the bits are exactly same. – Kayaman May 24 '16 at 10:48
  • My hashes match, my bytes don't. I don't see anything helpfull in that post. – user5581557 May 24 '16 at 10:49
  • My post is targeted at Sarathy, sorry Kayaman. – user5581557 May 24 '16 at 10:52
  • Are you trying to write something like `byte[] b = {177, 10, 141, 177, 100, 224};` in Java source code? – Kayaman May 24 '16 at 10:53
  • No, that wouldn't work. A file gets encrypted on c# side, the password bytes are then sent to Java in Hex format. When Java tries to decrypt the file it can't because the byte[] don't match. – user5581557 May 24 '16 at 10:55
  • 1
    @user5581557, that's wrong. If you're having problems decrypting the file in Java, it's not because Java uses signed bytes. – Louis Wasserman May 24 '16 at 18:17
  • @LouisWasserman You are correct, Java handled the bytes for me when decrypting and it was successful, the problem was with encoding which I fixed by converting the decrypted data to UTF-8. – user5581557 May 25 '16 at 08:35

2 Answers2

8

The bytes have identical values, they are just printed differently.

If you would like to ensure that bytes with negative values are displayed as positive numbers, add 256 and take modulo 256, like this:

for (byte b : byteArray) {
    int n = (b + 256) % 256;
    System.out.println(n);
}

Similarly, if you would like to bring your values above 128 into the proper range of byte, you can cast them to truncate the upper bytes and get negative values, or if you prefer you could subtract 256:

for (int n : byteValuesAsInt) {
    byte b1 = (byte)n;
    byte b2 = n >= 128 ? n-256 : n;
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • My objective is not to view the bytes, its to use them. In Java I cannot insert the values into a byte[] as It's unsigned. – user5581557 May 24 '16 at 10:51
  • 3
    Of course you can. Just cast them down to a byte. Whether it will end as a negative number is not relevant - the bytes representation is the same. – spi May 24 '16 at 10:52
  • Could you show an example of "casting down to a byte" please. – user5581557 May 24 '16 at 10:56
3

Java uses signed bytes, while C# uses unsinged ones. To compare strings, let's convert Java representation to C# one:

  String java = 
    "-79, 10, -115, -79, 100, -32, 117, 65, 5, -73, -87, -101, -25, 46, 63, -27";

  String cs = String.Join(", ", java
    .Split(',')
    .Select(c => int.Parse(c))
    .Select(x => x < 0 ? 256 + x: x));

 // 177, 10, 141, 177, 100, 224, 117, 65, 5, 183, 169, 155, 231, 46, 63, 229
 Console.Write(cs);

As you can see the strings are now equal.

EDIT: If you're given java string, and you want to have C# byte[]:

 byte[] cs = java
   .Split(',')
   .Select(c => int.Parse(c))
   .Select(x => (byte) (x < 0 ? 256 + x: x)))
   .ToArray();
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Okay thats perfect, but how can I use that string (result) in a function which takes a byte[] as a parameter? ex: decrypt(byte[],byte[]) – user5581557 May 24 '16 at 11:00
  • 1
    @user5581557: if you're given Java *string* (since there're negative values in the Java result you can't have `byte[]` in C# directly) you can convert it into c# `byte[]` via *Linq* (see my edit) – Dmitry Bychenko May 24 '16 at 11:05