C#无符号字节加密到Java签名字节解密

时间:2013-07-19 19:44:05

标签: c# java cryptography unsigned signed

我在C#中有一个应用程序使用RijndaelManaged加密部分文件(因为它们是大文件)。所以我将我的文件转换为字节数组并仅加密其中的一部分。

然后我想用Java解密文件。因此,我必须解密仅在C#中加密的部分(意味着那些字节)。

问题来了。因为在C#中我们有无符号字节,而在Java中我们有有符号字节。所以我的加密和解密不能按我想要的方式工作。

在C#中,我将加密的字节和普通字节加在一起,并用File.WriteAllBytes保存。所以我不能在这里使用 sbyte 或者我不知道该怎么做:

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

(并且在Java中解密的代码完全相同)

所以我的问题是:

  • C#中有 WriteAllsBytes 吗?
  • 或者我可以在Java中使用无符号字节吗?
  • 或者我的问题的其他任何解决方案?

1 个答案:

答案 0 :(得分:3)

虽然你不能在Java中使用无符号字节,但你可以忽略这个问题。

AES - 以及所有现代对称密码 - 按字节操作,输入和输出已定义为字节(或八位字节)。输入和输出已由NIST标准化,并且可以使用测试向量。

如果查看字节的单独位内容,那么C#中的{200,201,202}和Java中的{(byte)200, (byte)201, (byte)202}是相同的。这是因为Java使用字节的双补码表示。

将数字200作为整数:这将是二进制的11010000,如果在两个补码中的(带符号)字节中使用,则表示Java中的数字-56。现在,对称密码将简单地将这些位转换为另一个位(通常使用完整的位)。

一旦检索到答案,当您查看单独的位时,您将看到它们在C#和Java 中是相同的。但是,C#会将这些解释为无符号值,将Java解释为有符号值。

如果要在Java中打印或使用这些值作为带符号的数字,则必须将它们转换为正有符号整数。这样做的方法是使用int p = b & 0xFF

以下(我将再次使用数字200):

  1. (负)字节值扩展为有符号整数,记住符号位:

    11010000变为11111111 11111111 11111111 11010000

  2. 通过执行二元AND运算符,0xFF00000000 00000000 00000000 11111111对此值进行“屏蔽”:

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

  3. 此值与作为有符号整数的值200相同。