2

I have an application in C# that encrypt part of my files (because they are big files) using RijndaelManaged. So I convert my file to byte arrays and encrypt only a part of it.

Then I want to decrypt the file using Java. So I have to decrypt only part of the file (means those bytes) that was encrypted in C#.

Here the problem comes. Because in C# we have unsigned bytes and in Java we have signed bytes. So my encryption and decryption not working the way I want.

In C# I have joined the encrypted bytes and normal bytes together and saved them with File.WriteAllBytes. So I can't use sbyte here or I don't know how to do it:

byte[] myEncryptedFile = new byte[myFile.Length];
for (long i = 0; i < encryptedBlockBytes.Length; i++)
{
   myEncryptedFile[i] = encryptedBlockBytes[i];
}
for (long i = encryptedBlockBytes.Length; i < myFile.Length; i++)
{
   myEncryptedFile[i] = myFileBytes[i];

}

File.WriteAllBytes(@"C:\enc_file.big", myEncryptedFile);

( And there is an exact same code for decryption in Java )

So my questions are:

  • Is there any WriteAllsBytes in C#?
  • Or can I use unsigned bytes in Java?
  • Or any other solutions to my problem?
jmj
  • 237,923
  • 42
  • 401
  • 438
Vahid
  • 3,384
  • 2
  • 35
  • 69
  • http://stackoverflow.com/questions/4266756/can-we-make-unsigned-byte-in-java may be you can convert it to unsigned – jmj Jul 19 '13 at 19:47
  • I've checked that before. Unfortunately it didn't help. – Vahid Jul 19 '13 at 19:50
  • I don't get this question. If the bytes are used as numbers during mathematical operations then it does matter if the bytes are signed or unsigned. All known symmetric ciphers however treat the bytes as just a set of 8 bits (at least regarding input/output). `RijndaelManaged` does not seem to be an exception to this rule. In other words, you should not have any issue as long as your bytes contain the same bits in the right order. – Maarten Bodewes Jul 19 '13 at 20:54
  • @owlstead: For instance if this is my byte array in C#: {200,201,202} and then I encrypt and write it to a file, how Java could decrypt 'the encrypted array' into {200,201,202} when it doesn't have any unsigned byte array? – Vahid Jul 19 '13 at 21:17
  • Yes, you would get negative values if you would print out the bytes. But print each byte out using `& 0xFF` (which makes it a positive `int` value) and you should get the same values. The question is how you *interpret* the bytes. – Maarten Bodewes Jul 19 '13 at 21:24
  • Yes, you're right. But how can I use "cipher.doFinal(myBytes)" in Java? (This is my problem right now) – Vahid Jul 19 '13 at 21:27
  • 1
    This might be relevant: http://stackoverflow.com/a/11039059/1149773 @Natasha: In brief: Just use it like that. – Douglas Jul 19 '13 at 22:03
  • 2
    Just as you wrote it. If you want to represent `{200, 201, 202}` then write `{(byte)200, (byte)201, (byte)202}`, which does the opposite of `& 0xFF`. Just don't go over 255 of course as those values don't fit into a byte. – Maarten Bodewes Jul 19 '13 at 22:03
  • 2
    Have you actually tried this in Java, using signed bytes? Did you get any problems writing the file? If signs are a problem for you, try examining your data as hex rather than as signed numbers. – rossum Jul 20 '13 at 10:49
  • Whether an integer type is signed is only relevant during addition, subtraction, division, and right shift (and of course when converting the number to a string). AES does not use any of these operations, except right shift – but Java provides the `>>>` operator, which performs an *unsigned right shift*. – ntoskrnl Jul 21 '13 at 10:50
  • @Natasha have we solved your problem by now or are you still unsure? – Maarten Bodewes Jul 21 '13 at 15:09

1 Answers1

6

Although you cannot use unsigned bytes in Java, you may simply ignore the issue.

AES - and all modern symmetric ciphers - operates on bytes, and the input and output have been defined to be bytes (or octets). Input and output have been standardized by NIST and test vectors are available.

If you look at the separate bit content of the bytes then {200,201,202} in C# and {(byte)200, (byte)201, (byte)202} in Java are identical. This is because Java uses two-complement representation of bytes.

Take the number 200 as integer: this will be 11010000 in binary, representing the number -56 in Java if used in a (signed) byte in two complements. Now symmetric ciphers will simply transform these bits to another (normally using a full block of bits).

Once you have retrieved the answer you will see that they are identical both in C# and Java when you look at the separate bits. C# will however interpret those as unsigned values and Java as signed values.

If you want to print out or use these values as signed numbers in Java then you have to convert them to positive signed integers. The way to do this is to use int p = b & 0xFF.

This does the following (I'll use the number 200 again):

  1. The (negative) byte value is expanded to a signed integer, remembering the sign bit:

    11010000 becomes 11111111 11111111 11111111 11010000

  2. This value is "masked" with 0xFF or 00000000 00000000 00000000 11111111 by performing the binary AND operator:

    11111111 11111111 11111111 11010000 & 00000000 00000000 00000000 11111111 = 00000000 00000000 00000000 11010000

This value is identical to the value 200 as a signed integer.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Although I have found the solution using BinaryWriter.Write(SByte) in C#, but your answer is worth to be checked. Thanks for the information. – Vahid Jul 26 '13 at 07:47