Java vs .NET中的DES加密 - 为什么不同?

Sha*_*ica 5 c# java encryption cryptography

我有一个.NET方法,用于对字符串进行DES加密:

public static string EncryptTripleDES(string value, byte[] encryptionKey, byte[] initializationVector) {
  if (!value.IsNullOrEmpty()) {
    TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, cryptoProvider.CreateEncryptor(encryptionKey, initializationVector), CryptoStreamMode.Write);
    StreamWriter sw = new StreamWriter(cs);
    sw.Write(value);
    sw.Flush();
    cs.FlushFinalBlock();
    ms.Flush();
    //convert back to a string
    return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
  } else {
    return "";
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,该算法采用2个参数 - "加密密钥"和"初始化向量".

现在我需要用Java编写DES加密/解密函数,与此函数并行,这样如果你提供相同的加密密钥和初始化向量,你将能够用Java解密用C#加密的东西.(关于Java工作服,自上次使用Java以来​​大约10年的时间,以及Java中用于DES加密的Googles ......)

在这里找到了一个不错的Java DES加密方法.但是 - 哦,亲爱的,事实证明这个算法坚持一个正好8个字节的初始化向量; .NET代码使用24字节的init向量!

怎么办?为什么Java坚持使用8字节的init向量?我如何解密使用24字节初始向量加密的内容?

laz*_*laz 2

您是否尝试过在 Java 代码中使用 24 字节初始化向量的前 8 个字节?我通过搜索和查看源代码看到的所有内容都表明,由于 Triple DES 的块大小为 8 字节,因此只会使用前 8 个字节。我真的很惊讶 .NET 代码没有引发像这个问题中提到的异常,因为 IV 与算法的块大小不匹配。另外,请参阅此问题以获取成功使用 8 字节 IV 的示例。

.NET 代码中的另一项挑战是填充和密码模式使用默认值。我不知道 .NET 将使用什么来实现这些,尽管此处的注释表明默认的密码模式是 CBC。我没有看到提到填充,但从这里的互操作性示例来看,CBC 和 PKCS5Padding 似乎可以工作。不过,我不愿意依赖默认值来实现这样的互操作性,因为它们可能会出现问题。

来自 Java 背景的我不太确定使用 24 字节 IV 的 C# 代码中发生了什么,但 Java 强制执行的 8 字节 IV 对我来说似乎是正确的。我总是对被证明是错误的并学习新东西感兴趣。@Tim 提到的 Bouncycastle 也强制执行相同的约束,并且 .NET 通常也会这样做。