Java解密返回的一些块中的错误

时间:2013-08-28 01:15:36

标签: c# java encryption

我遇到了用C#加密的Java字节解密问题。

Java的输出在五个明文块的最后两个中都有错误。第四个块是完全错误的,第五个块有一个字符错误。

我已经仔细检查/注意的事情:

  • Keys和IV是相同的,虽然我必须在末尾重复16位C#键的第一个字节来创建一个24位Java密钥。
  • C#正在使用CBC和PKCS7。 Blocksize是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;
    }          
}

我期待在sys上看到明文块。 我知道.update()循环可以替换为.doFinal()但我想逐块看到它。

我对Java不太熟悉,所以我特别感谢那里有任何建议。

修改 我不相信文本编码是问题。这是展示相同问题的原始代码,只是没有显示它的逐块性质:

byte[] decrypted = c.doFinal(inputByteArray);
return new String(decrypted, "UTF-8");

3 个答案:

答案 0 :(得分:0)

你不能采取任意的utf-8字节块并将它们转换为字符串(同样,你没有指定字符集)。你需要将所有字节放在一起并将它们转换为String,指定"UTF-8"字符集。

答案 1 :(得分:0)

Java通常具有与C#不同的默认值,因此您不应该在任何地方依赖默认值,特别是在字节和字符串之间进行转换时。除了@jtahlborn关于在任意点破坏UTF-8字符串的评论之外,您还需要在Java代码中指定UTF-8,就像在C#代码中所做的那样:

System.out.println(new String(decryptedBytes, "UTF-8"));

您可能想尝试检查实际字节,而不是检查字符。这应该可以让你更好地处理可能发生错配的地方。

答案 2 :(得分:0)

事实证明,这毕竟不是加密。

问题在于BASE64编码以及它已经通过cookie传播的事实,它已经将+变成了一个空格(所以感谢rossum的逐字节建议)。