Java解密返回的某些块中存在错误
本文关键字:存在 错误 解密 返回 Java | 更新日期: 2023-09-27 18:29:11
我在用C#加密的Java字节进行解密时遇到问题。
Java的输出在五个明文块中的最后两个块中有错误。第四块是完全错误的,第五块只有一个字符错误。
我反复检查/注意的事项:
- Keys和IV是相同的,尽管我必须在末尾重复16位C#密钥的第一个字节才能创建24位Java密钥
- C#正在使用CBC和PKCS7。块大小为8
- Java正在使用CBC和PKCS5(为此,应该与7相同)
这是C中的加密端#
byKey = Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
byte[] inputByteArray = Encoding.UTF8.GetBytes(val);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byKey, IV), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
以及Java中的解密
byte[] inputByteArray = Base64.decode(val);
Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(byKey, "DESede"), new IvParameterSpec(iv, 0, 8));
byte[] decryptedBytes;
for (int i = 0, j = 0; i < inputByteArray.length; i++) {
if ((decryptedBytes = c.update(inputByteArray, i, 1)) == null)
continue;
else {
System.out.println(new String(decryptedBytes));
j += decryptedBytes.length;
}
}
我希望看到系统上的明文块。我知道.update()循环可以用.doFinal()代替,但我想一块一块地看。
我对Java不是很熟悉,所以如果有任何建议,我将不胜感激。
编辑我不认为文本编码是问题所在。以下是显示相同问题的原始代码,只是没有显示它的逐块性质:
byte[] decrypted = c.doFinal(inputByteArray);
return new String(decrypted, "UTF-8");
您不能将utf-8字节的任意块转换为字符串(此外,您没有指定字符集)。您需要将所有字节放在一起,并将它们转换为String,指定"UTF-8"
字符集。
Java通常对C#有不同的默认值,因此您不应该在任何地方依赖默认值,尤其是在字节和字符串之间转换时。除了@jtahlborn关于在任意点中断UTF-8字符串的评论外,您还需要在Java代码中指定UTF-8,就像在C#代码中所做的那样:
System.out.println(new String(decryptedBytes, "UTF-8"));
与其检查字符,不如尝试检查实际字节。这应该能让你更好地了解哪里可能发生了不匹配。
事实证明这根本不是加密。
问题出在BASE64编码上,事实上它是通过一个cookie传播的,这个cookie将+变成了一个空格(所以感谢rossum的逐字节建议)。