0

I am tiring to converting encription logic in to java which written in C#. I pass a custom IV as parameter.

 private static byte[] iv = new byte[] { 116,209,63,154,85,66,37,82,96,104,131,192,103,140,125,176 };

But, In java can not hold more then 128 in a byte array. In C# it is possible.

        this.secretKeySpec = new SecretKeySpec(key, "AES");
        this.iv = new IvParameterSpec(iv);
        this.cipher = Cipher.getInstance(ALGORITHM_AES256);

In javax.crypto IvParameterSpec constactory only allow byte array as "iv". Can anyone please help for pass above byte[] as iv parameter in java.

Dinusha
  • 696
  • 1
  • 14
  • 27
  • [similar](http://stackoverflow.com/questions/2346101/java-how-to-use-byte-literals-greater-than-0x7f) [questions](http://stackoverflow.com/questions/9241336/initialize-unsigned-byte-array-using-hex-number) that could be considered duplicates. – Oleg Estekhin Jun 29 '14 at 13:57
  • You should not use static IV's in the first place. Static IV's are useless. – Maarten Bodewes Jun 29 '14 at 14:54

2 Answers2

2

The problem is that Java does not support unsigned datatypes, while .NET does.

Unsigned byte is from 0 to 255. This is .NET Byte struct
Signed byte is from -128 to 127. This is Java byte primitive datatype or .NET SByte struct.

The data in .Net code stores the iv as unsigned values, while Java code does not allow you to do it directly.

Solutions:

1) You could just manually subtract 128 from each byte in .NET code, thus making it to represent the same bit pattern(IV is just sequence of bits - it does not matter whether they stored as signed or unsigned values - it is the bits that must match):

byte[] iv = new byte[] { -8, 81, ...};

2) Or you could store the same data in an int datatype array and convert them to byte values using the following code.

int[] ivInInts = new int[] { 116,209,63,154,85,66,37,82,96,104,131,192,103,140,125,176 };

byte[] iv = new byte[ivInInts.getLength()];

for (int i = 0; i < ivInInts.getLength(); i++)
   iv = (byte)(ivInInts[i] - 128);

EDIT:

If you have some doubts about binary equivalence of numbers you could read about two's complement numbers:

65 = 0100 0001 as unsigned byte = 0100 0001 as signed byte
-65 = cannot be represented as unsigned byte = 1011 1111 as signed byte
193 = 1011 1111 as unsigned byte = cannot be represented as signed byte

Community
  • 1
  • 1
Eugene Podskal
  • 10,270
  • 5
  • 31
  • 53
  • Thanks Eugene, If we subtract -128 from each element in the array the result array will have (-) value not the same what it pass in C#. Is that ok? – Dinusha Jun 29 '14 at 13:31
  • @Eugene Podskal You're not correct. Unsigned 8-bit integer is from 0 to 255, and the signed 8-bit integer or sbyte is from -128 to 127. Please, correct it. – GoRoS Jun 29 '14 at 13:32
  • @GoRoS Thank you. Just misplaced the strings. – Eugene Podskal Jun 29 '14 at 13:38
1

Alternative to Eugene's proposal: simply explicitly convert all values - or the values above 127 - by casting to a byte. It's also a good idea to use hexadecimals for binary data.

byte[] test = new byte[] { 0, (byte) 0, 0x00, (byte) 0x00, (byte) 128, (byte) 0x80, (byte) 256, (byte) 0x100 };

Note that - as the value of the last two bytes should make clear - this does allow you to specify values that are out of range without raising a warning.

Alternatively, you could use a hexadecimal or base64 decoder, so you can create more dense byte array representation using strings.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263