2014-06-29 135 views
0

我很累人地将encription逻辑转换成用C#编写的java。我传递一个自定义IV作为参数。通过传递IV加密AES 256

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

但是,在java中,不能在一个字节数组中保存多于128个。在C#中是可能的。

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

在javax.crypto中,IvParameterSpec constactory只允许字节数组为“iv”。任何人都可以请帮助传递上面的byte []作为iv参数在Java中。

+0

[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)可能被认为是重复的。 –

+0

您不应该首先使用静态IV。静态IV是无用的。 –

回答

2

问题是,Java不支持unsigned datatypes,而.NET。

无符号字节是从0到255这是.NET Byte结构
符号字节是从-128到127这是爪哇byte原始数据类型或.NET SByte结构。

.Net代码中的数据将iv存储为无符号值,而Java代码不允许您直接执行此操作。

解决方案:

1)你可以只手动从在.NET代码的每个字节中减去128,从而使得来表示相同的比特模式(IV只是位的序列 - 它并不重要是否它们存储为符号或无符号值 - 这是必须匹配的位):

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

2),或者你可以存储在一个int数组数据类型相同的数据并将其转换为使用下面的代码的字节值。

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); 

编辑:

如果您有关于数字的二进制等价有些疑惑,你可以读到two's complement numbers

65 = 0100 0001为无符号字节= 0100 0001为符号字节
-65 =不能表示为无符号字节= 1011 1111作为有符号字节
193 = 1011 1111作为无符号字节=不能表示为有符号字节

+0

感谢尤金,如果我们从数组中的每个元素中减去-128,那么结果数组将具有( - )值与C#中传递的值不同。这可以吗? – Dinusha

+0

@Eugene Podskal你是不正确的。无符号的8位整数是从0到255,有符号的8位整数或sbyte是从-128到127.请纠正它。 – GoRoS

+0

@GoRoS谢谢。只是放错了字符串。 –

1

替代尤金的建议:只需将所有值或127以上的值转换为byte即可。为二进制数据使用十六进制也是一个好主意。

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

请注意,作为最后两个字节的值应该清楚 - 这确实允许您指定超出范围而不会引发警告的值。

或者,您可以使用十六进制或base64解码器,因此您可以使用字符串创建更密集的字节数组表示形式。