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

时间:2011-05-19 11:49:01

标签: 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 "";
  }
}

如您所见,该算法采用2个参数 - “加密密钥”和“初始化矢量”。

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

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

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

3 个答案:

答案 0 :(得分:2)

From MSDN

  

自动设置IV属性   每当你到一个新的随机值   创建其中一个的新实例   SymmetricAlgorithm类或当你   手动调用GenerateIV方法。   IV属性的大小必须是   与BlockSize属性相同。

所以在我看来你可以简单地改变BlockSize属性,然后你可以将IV设置为你需要的任何大小。

修改

根据我在研究中收集的内容,似乎DES加密算法的所有实现都使用8个字节(64位,其中8个被丢弃,留下56个字节)。 TripleDES(3DES)允许24字节的密钥(或192位,其中24位被丢弃,留下168位)。

您似乎需要在Java中使用TripleDES算法(有几个库可用,exampleSO Question),或者您需要使用常规DES重新加密数据.NET中的加密算法。

答案 1 :(得分:2)

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

.NET代码中的另一个挑战是默认值用于填充和密码模式。我不知道.NET将用于那些,尽管备注here表明默认密码模式是CBC。我没有看到填充,但是从互操作性示例here来看,似乎CBC和PKCS5Padding都可以工作。我会毫不犹豫地依赖默认设置这样的互操作性,因为它们可能会有问题。

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

答案 2 :(得分:0)

您是否看过Bouncy Castle Java库?我无法从他们的(非常稀疏的)文档和样本中看出来,但它似乎是一个广泛使用的库,所以我希望它是那么灵活。值得一看,如果你还没有。