Java 与 .NET 中的 DES 加密 - 为什么不同?
我有一个对字符串进行 DES 加密的 .NET 方法:
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 年了,Google 搜索 Java 中的 DES 加密......)
找到了一种不错的 Java DES 加密方法 此处。但是 - 天哪,事实证明该算法坚持使用恰好 8 个字节的初始化向量; .NET 代码使用 24 字节的初始化向量!
现在怎么办?为什么 Java 坚持使用 8 字节的初始化向量?如何解密使用 24 字节初始化向量加密的内容?
I have a .NET method for doing DES encryption on a string:
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 "";
}
}
As you see, the algorithm takes 2 parameters - an "encryption key" and an "initialization vector".
Now I need to write a DES encryption/decryption function in Java, paralleling this function, such that if you supply the same encryption key and initialization vector, you'll be able to decrypt in Java something that was encrypted in C#. (Puts on Java overalls, dusts off about 10 years since last using Java, Googles for DES encryption in Java...)
Found a decent Java DES encryption approach here. But - oh dear, it turns out that this algorithm insists on an initialization vector of exactly 8 bytes; the .NET code uses an init vector of 24 bytes!
Now what? Why does Java insist on an 8-byte init vector? And how can I decrypt something that was encrypted using a 24-byte init vector?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您是否尝试过在 Java 代码中使用 24 字节初始化向量的前 8 个字节?我通过搜索和查看源代码看到的所有内容都表明,由于 Triple DES 的块大小为 8 字节,因此只会使用前 8 个字节。我真的很惊讶 .NET 代码没有引发像 此问题,因为 IV 与算法的块大小不匹配。另请参阅此问题,了解以下示例: 8字节IV已成功使用。
.NET 代码中的另一项挑战是填充和密码模式使用默认值。我不知道 .NET 将用于这些,尽管注释 这里表示默认的ciphermode是CBC。我没有看到提到填充,但从互操作性示例 这里,似乎CBC和PKCS5Padding可以工作。不过,我不愿意依赖默认值来实现这样的互操作性,因为它们可能会出现问题。
来自 Java 背景的我不太确定使用 24 字节 IV 的 C# 代码中发生了什么,但 Java 强制执行的 8 字节 IV 对我来说似乎是正确的。我总是对被证明是错误的并学习新东西感兴趣。 @Tim 提到的 Bouncycastle 也强制执行相同的约束,并且 .NET 通常也会这样做。
Have you tried using the first 8 bytes of the 24 byte initialization vector in the Java code? Everything I'm seeing through searching and looking at source code indicates that only the first 8 bytes would be used since Triple DES has an 8 byte block size. I'm really surprised that the .NET code doesn't raise an exception like the one mentioned in this question since the IV doesn't match the algorithm's block size. Also, see this question for examples where the 8 byte IV is used successfully.
One additional challenge in the .NET code is that default values are used for the padding and ciphermode. I don't know what .NET will use for those, although the remarks here indicate that the default ciphermode is CBC. I see no mention of padding, but from the interoperability example here, it seems that CBC and PKCS5Padding will work. I'd hesitate to rely on defaults for interoperability like this though, as they can be problematic.
Coming from a Java background I'm not really sure what is going on in the C# code using a 24 byte IV, but the 8 byte IV enforced by Java seems to be correct to me. I'm always interested in being proven wrong and learning something new though. Bouncycastle as mentioned by @Tim also enforces this same constraint and it seems like .NET usually does also.
来自 MSDN:
所以在我看来,您可以简单地更改 BlockSize 属性,然后可以将 IV 设置为您需要的任何大小。
编辑
根据我在研究中收集到的信息,似乎 DES 加密算法的所有实现都使用 8 个字节(64 位,其中 8 位被丢弃,只剩下 56 个字节)。 TripleDES (3DES) 允许使用 24 字节(或 192 位,其中 24 位被丢弃,只剩下 168 位)的密钥。
看来您需要在 Java 中使用 TripleDES 算法(有几个可用的库,示例,SO问题),否则您将需要使用 .NET 中的常规 DES 加密算法重新加密您的数据。
From MSDN:
So it seems to me that you can simply change the BlockSize property, and you can then set the IV to whatever size you need.
EDIT
From what I have gathered in my research, it seems that all implementations of the DES encryption algorithm use 8 bytes (64 bits, 8 of which get thrown away, leaving you with 56 byte). TripleDES (3DES) allows for a key of 24 bytes (or 192 bits, 24 of which get thrown away, leaving you with 168 bits).
It seems that you will either need to use a TripleDES algorithm in Java (several libraries are available, example, SO Question), or you will need to re-encrypt your data using the regular DES encryption algorithm in .NET.
您是否看过 Java 的 Bouncy Castle 库?我无法从他们的(非常稀疏的)文档和示例中看出,但它似乎是一个广泛使用的库,所以我希望它能那么灵活。至少值得一看(如果您还没有看过的话)。
Have you taken a look at the Bouncy Castle library for Java? I can't tell from their (very sparse) documentation and samples, but it seems like a widely used library so I'd hope it'd be that flexible. Worth taking a look at least if you haven't already.