将C#加密转换为Java
我的任务是将一种C#加密方法转换成Java,我被卡住了。我知道C#代码可以工作,但我在让Java代码工作时遇到了麻烦 以下是C#代码: 更多信息将C#加密转换为Java,java,c#,encryption,aes,rijndael,Java,C#,Encryption,Aes,Rijndael,我的任务是将一种C#加密方法转换成Java,我被卡住了。我知道C#代码可以工作,但我在让Java代码工作时遇到了麻烦 以下是C#代码: 更多信息 对于GetIV和GetKey,我可以保证java中的结果是相同的(我已经比较了每个字节),但我不包括这些方法,因为我认为这是敏感信息。我还可以保证输入字节[]相同且(冗余地)长度相同 调试尝试:Java中的当前错误是ECB模式无法使用IV 当我删除此代码时:new-IvParameterSpec(getIV())我得到此错误:错误的算法:需要AES
- 对于
和GetIV
,我可以保证java中的结果是相同的(我已经比较了每个字节),但我不包括这些方法,因为我认为这是敏感信息。我还可以保证输入字节[]相同且(冗余地)长度相同GetKey
- 调试尝试:Java中的当前错误是
ECB模式无法使用IV
- 当我删除此代码时:
我得到此错误:new-IvParameterSpec(getIV())
错误的算法:需要AES或Rijndael
- 如果我将算法更改为仅
或仅AES
我会得到以下错误:Rijndael
使用填充密码解密时,输入长度必须是16的倍数。读取/删除前4个字节后,输入长度开始为
和424
。我已经验证了Java和C的输入字节是相同的420
- 当我删除此代码时:
Java代码中的错误在哪里?您得到了错误
ECB模式不能使用IV
,因为ECB不执行链接,所以IV没有意义。区别在于Java抛出了一个错误,而C#只是忽略了IV
当我删除此代码时:新的IvParameterSpec(getIV())
我得到此错误:错误的算法:
AES或Rijndael
必需
如果将算法更改为仅AES或仅Rijndael,则会出现以下错误:使用填充密码解密时,输入长度必须是16的倍数。
你的想法是对的,但你做得太过分了。此错误仅与SecretKeySpec
有关,它不关心模式,只关心算法<代码>密码是指定模式的地方。此外,Rijndael和AES也不是一回事
因此,首先将前几行更改为:
Cipher cipher = Cipher.getInstance("Rijndael/ECB/NoPadding");
byte[] key = getKey(input[1]);
SecretKey secretKey = new SecretKeySpec(key, 0, key.length, "Rijndael");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
请注意,由于您使用的是整个键
,因此不需要offset和length参数,因此只需执行以下操作即可
SecretKey secretKey = new SecretKeySpec(key, "Rijndael");
原始C#代码有一些不太明显的行为:
while ((bytes = input.Read(buffer, 0, BufferSize)) > 0)
{
for (int i = 0; i < bytes; i += rijndael.BlockSize)
{
decryptor.TransformBlock(buffer, i, rijndael.BlockSize, buffer, i);
}
output.Write(buffer, 0, bytes);
}
while((字节=input.Read(buffer,0,BufferSize))>0)
{
for(int i=0;i
当循环到达输入
的末尾时,它将把剩余的部分复制到缓冲区
。除非最后一次读取
正好是1024字节,否则在输入结束后,上一个循环(如果它通过一次读取
操作获得整个输入
,则来自初始化)将有剩余
内部循环一次解密一个16字节的块。在420字节的示例中,最后一个块将由剩余的4个字节的输入和另外12个字节的垃圾组成。但这没关系,因为output.Write
只写入字节数
以截断垃圾。您必须在Java代码中复制这种行为
旁注:你一定要使用ECB吗?不太安全…非常感谢。当我应用您的更改时,出现以下错误:
输入长度不是16字节的倍数
。这与我遇到的另一个错误类似,只是它没有说明任何关于填充的内容。我尝试删除输入数组的最后4个字节(以及前4个字节),因为最后4个字节是填充的,以使长度为16的倍数,这非常有效,解密后的字符串末尾只有一些奇怪的字符……我忘了提一下,你也不会像原来的C#那样截断最终结果(output.SetLength(output.Length-pad-4);
),这也会影响你的结果。是的,我认为不太明显的行为是最后一个部分。一旦我把它转换成Java,它就工作了!再次感谢!!
SecretKey secretKey = new SecretKeySpec(key, "Rijndael");
while ((bytes = input.Read(buffer, 0, BufferSize)) > 0)
{
for (int i = 0; i < bytes; i += rijndael.BlockSize)
{
decryptor.TransformBlock(buffer, i, rijndael.BlockSize, buffer, i);
}
output.Write(buffer, 0, bytes);
}