2

我有一个用 C++ 为 Windows 编写的现有应用程序。此应用程序使用 Win32 CryptoAPI 生成 TripleDES 会话密钥,用于加密/解密数据。我们使用一个技巧的指数将会话密钥导出为 blob,这允许 blob 以解密格式存储在某处。

问题是我们如何在 .NET 应用程序 (C#) 中使用它。该框架封装/包装了 CryptoAPI 所做的大部分工作。部分问题是 CryptAPI 指出Microsoft 增强加密提供程序的 TripleDES 算法是 168 位(3 个 56 位的密钥)。但是,.NET 框架声明它们的密钥是 192 位(3 个 64 位的密钥)。显然,.NET 框架中的 3 个额外字节是为了奇偶校验?

无论如何,我们需要从 blob 中读取关键部分,并且能够以某种方式在我们的 .NET 应用程序中使用它。目前,当我们尝试在 .NET 中使用密钥时,我们没有得到预期的结果。解密失败得很惨。任何帮助将不胜感激。

更新:

我一直在想办法解决这个问题,并提出了一个我会及时发布的解决方案。但是,仍然会感谢其他人的任何反馈。

4

2 回答 2

5

介绍

我终于开始发布解决方案了。我希望它为可能正在做类似事情的其他人提供一些帮助。在其他地方这样做真的没有太多参考。

先决条件

为了使其中的大部分内容有意义,有必要读取一个技巧的指数,它允许您将会话密钥导出到 blob(一种众所周知的字节结构)。然后可以用这个字节流做他们想做的事,但它拥有所有重要的密钥。

MSDN 文档令人困惑

在这个特定示例中,我使用Microsoft Enhanced Cryptographic Provider和 Triple DES ( CALG_3DES ) 算法。让我陷入循环的第一件事是密钥长度以 168 位列出,块长度为 64 位。密钥长度怎么可能是168?三个 56 位的密钥?另一个字节会发生什么?

因此,有了这些信息,我开始在其他地方阅读最后一个字节是如何真正奇偶校验的,无论出于何种原因,CryptoAPI 都会将其剥离。真的是这样吗?他们会这样做似乎有点疯狂,但没关系。

.NET 中密钥的使用

使用TripleDESCryptoServiceProvider,我注意到文档中的注释表明:

该算法支持从 128 位到 192 位的密钥长度,以 64 位为增量。

因此,如果 CryptoAPI 的密钥长度为 168,我将如何将其放入仅支持 64 倍数的 .NET 中?因此,API 的 .NET 端考虑了奇偶性,而 CryptoAPI 没有。可以想象……我很困惑

因此,通过所有这些,我试图弄清楚如何使用正确的奇偶校验信息在 .NET 端重建密钥。可行,但不是很有趣……我们就这样吧。一旦我完成了所有这些,一切都以 CAPITAL F告终。

还在我这儿?很好,因为我又从马上摔下来了。

灯泡和烟花

低,看,当我在 MSDN 中搜索最后一点信息时,我在 Win32 CryptExportKey函数中发现了一个冲突的部分。低,我发现了这条无价的信息:

对于任何使用 PLAINTEXTKEYBLOB 的 DES 密钥排列,只能导出完整的密钥大小,包括奇偶校验位。支持以下密钥大小。

算法支持的密钥大小

CALG_DES 64 位

CALG_3DES_112 128 位

CALG_3DES 192 位

所以它确实导出了一个 64 位的倍数的密钥!呜呼!现在修复.NET 端的代码。

.NET 导入代码调整

在导入包含从 CryptoAPI 作为 blob 导出的密钥的字节流时,请牢记字节顺序。这两个 API 不使用相同的字节顺序,因此,正如@nic-strong所指出的,在实际尝试使用密钥之前反转字节数组是必不可少的。除此之外,事情按预期工作。简单解决:

Array.Reverse( keyByteArray );

结论

我希望这可以帮助那里的人。我花了太多时间试图追踪这一点。如果您还有其他问题,请留下任何评论,我可以尝试帮助填写任何详细信息。

快乐的加密货币!

于 2008-12-06T01:26:28.080 回答
1

好的,忘记我看不懂的最后一个答案 :) 您正在使用 3Des 密钥而不是 RSA 密钥。

我编写了一堆代码来在 .NET、CryptoAPI 和 openssl 之间共享密钥。在这里找到了很多很好的示例代码来进行关键转换:

http://www.jensign.com/JavaScience/cryptoutils/index.html

其中一些示例中有一些 3des 的东西,但它与 openssl -> .NET iirc 有关。

我也刚刚回顾了 RSA 密钥代码,我注意到我正在做的一件事是在 RSA 密钥的所有关键部分(D、DP、DQ、InverseQ、Modulus、P、Q)上使用 Array.Reverse()猜想转换字节序。我记得在第一次解决问题时并不明显。

希望其中一些有所帮助。祝你好运。

于 2008-09-08T06:24:31.910 回答