如何在 .NET 应用程序中使用从 Win32 CryptoAPI 生成的密钥 blob?
我有一个用 C++ 编写的 Windows 现有应用程序。 此应用程序使用 Win32 CryptoAPI 生成用于加密/解密数据的 TripleDES 会话密钥。 我们使用一个技巧的指数将会话密钥导出为一个blob,这允许 blob 以解密格式存储在某处。
问题是我们如何在 .NET 应用程序 (C#) 中使用它。 该框架封装/包装了 CryptoAPI 正在执行的大部分操作。 部分问题是 CryptAPI 声明 Microsoft 增强型加密提供程序 为 168 位(3 个 56 位密钥)。 然而,.NET 框架声明它们的密钥是 192 位(3 个 64 位密钥)。 显然,.NET框架中的3个额外字节是为了奇偶校验?
不管怎样,我们需要从 blob 中读取关键部分,并以某种方式能够在我们的 .NET 应用程序中使用它。 目前,当我们尝试在 .NET 中使用该密钥时,我们没有得到预期的结果。 解密惨遭失败。 任何帮助将不胜感激。
更新:
我一直在研究解决此问题的方法,并提出了一个解决方案,我将及时发布。 但是,仍然希望得到其他人的任何反馈。
I have an existing application that is written in C++ for Windows. This application uses the Win32 CryptoAPI to generate a TripleDES session key for encrypting/decrypting data. We're using the exponent of one trick to export the session key out as a blob, which allows the blob to be stored somewhere in a decrypted format.
The question is how can we use this in our .NET application (C#). The framework encapsulates/wraps much of what the CryptoAPI is doing. Part of the problem is the CryptAPI states that the TripleDES algorithm for the Microsoft Enhanced Cryptographic Provider is 168 bits (3 keys of 56 bits). However, the .NET framework states their keys are 192 bits (3 keys of 64 bits). Apparently, the 3 extra bytes in the .NET framework is for parity?
Anyway, we need to read the key portion out of the blob and somehow be able to use that in our .NET application. Currently we are not getting the expected results when attempting to use the key in .NET. The decryption is failing miserably. Any help would be greatly appreciated.
Update:
I've been working on ways to resolve this and have come up with a solution that I will post in time. However, still would appreciate any feedback from others.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好的,忘记最后一个我看不懂的答案:) 您正在使用 3Des 密钥而不是 RSA 密钥。
我编写了一堆代码来在 .NET、CryptoAPI 和 openssl 之间共享密钥。 在这里找到了很多很好的示例代码来进行关键转换:
http://www.jensign.com/javascience/cryptoutils/index.html jensign.com/JavaScience/cryptoutils/index.html
其中一些示例中有一些 3des 内容,但它与 openssl -> 相关。 .NET iirc。
我还回顾了 RSA 密钥代码,我注意到我正在做的一件事是在 RSA 密钥的所有关键部分(D、DP、DQ、InverseQ、Modulus、P、Q)上使用 Array.Reverse() i猜测转换字节序。 我记得第一次解决这个问题时,这一点并不明显。
希望其中一些有所帮助。 祝你好运。
Ok, forget the last answer I can't read :) You are working with 3Des keys not RSA keys.
I worked on a bunch of code to share keys between .NET, CryptoAPI and openssl. Found a lot of good example code here for doing the key conversions:
http://www.jensign.com/JavaScience/cryptoutils/index.html
There is some 3des stuff in some of those examples, but it was related to openssl -> .NET iirc.
I also just looked back over the RSA key code and one thing I notice I am doing is using Array.Reverse() on all the key parts of the RSA key (D,DP,DQ,InverseQ,Modulus,P,Q) i guess to convert endian. I remember that being non-obvious when first tackling the problem.
Hope some of that helps. Good luck.
简介
我终于开始发布解决方案了。 我希望它能为可能正在做类似事情的其他人提供一些帮助。 在其他地方确实没有太多这样做的参考。
先决条件
为了让其中的大部分内容有意义,有必要阅读一个技巧的指数< /em>,它允许您将会话密钥导出到 blob(一种众所周知的字节结构)。 然后,人们可以用这个字节流做他们想做的事,但它保存着所有重要的密钥。
MSDN 文档令人困惑
在这个特定的示例中,我使用 Microsoft 增强型加密提供程序,采用三重 DES (CALG_3DES) 算法。 首先让我困惑的是密钥长度为 168 位,块长度为 64 位。 密钥长度怎么可能是168呢? 三个 56 位密钥? 另一个字节会发生什么?
因此,有了这些信息,我开始在其他地方阅读最后一个字节是如何真正奇偶校验的,以及出于某种原因 CryptoAPI 删除了它。 真的是这样吗? 他们这样做似乎有点疯狂,但没关系。
在 .NET 中使用密钥
使用 TripleDESCryptoServiceProvider,我注意到文档中的注释表明:
因此,如果 CryptoAPI 的密钥长度为 168,我如何将其放入仅支持 64 倍数的 .NET 中? 因此,API 的 .NET 端会考虑奇偶校验,而 CryptoAPI 则不会。 正如人们可以想象的...我很困惑。
因此,通过所有这些,我试图找出如何使用正确的奇偶校验信息在 .NET 端重建密钥。 可行,但不是很有趣......让我们就这样吧。 当我完成所有这些后,一切都以大写 F 失败告终。
还在我这儿? 很好,因为我刚刚又从马上摔下来了。
灯泡和烟花
瞧,当我在 MSDN 上搜寻最后一点信息时,我在 Win32 中发现了一个相互冲突的部分 CryptExportKey 函数。 瞧,我发现了这条非常宝贵的信息:
因此,它确实导出一个 64 位倍数的密钥! 呜呼! 现在修复 .NET 端的代码。
.NET 导入代码调整
在导入包含从 CryptoAPI 作为 blob 导出的密钥的字节流时,请务必牢记字节顺序。 这两个 API 不使用相同的字节顺序,因此,如 @nic-strong 表示,在实际尝试使用密钥之前反转字节数组至关重要。 除此之外,一切都按预期进行。 简单解决:
结论
我希望这对那里的人有帮助。 我花了太多时间试图找出这一点。 如果您还有其他问题,请留下任何评论,我可以尝试帮助填写任何详细信息。
加密货币快乐!
Intro
I'm Finally getting around to posting the solution. I hope it provides some help to others out there that might be doing similar type things. There really isn't much reference to doing this elsewhere.
Prerequisites
In order for a lot of this to make sense it's necessary to read the exponent of one trick, which allows you to export a session key out to a blob (a well known byte structure). One can then do what they wish with this byte stream, but it holds the all important key.
MSDN Documentation is Confusing
In this particular example, I'm using the Microsoft Enhanced Cryptographic Provider, with the Triple DES (CALG_3DES) algorithm. The first thing that threw me for a loop was the fact that the key length is listed at 168 bits, with a block length of 64 bits. How can the key length be 168? Three keys of 56 bits? What happens to the other byte?
So with that information I started to read elsewhere how the last byte is really parity and for whatever reason CryptoAPI strips that off. Is that really the case? Seems kind of crazy that they would do that, but OK.
Consumption of Key in .NET
Using the TripleDESCryptoServiceProvider, I noticed the remarks in the docs indicated that:
So if CryptoAPI has key lengths of 168, how will I get that into .NET which supports only supports multiples of 64? Therefore, the .NET side of the API takes parity into account, where the CryptoAPI does not. As one could imagine... confused was I.
So with all of this, I'm trying to figure out how to reconstruct the key on the .NET side with the proper parity information. Doable, but not very fun... let's just leave it at that. Once I got all of this in place, everything ended up failing with a CAPITAL F.
Still with me? Good, because I just fell off my horse again.
Light Bulbs and Fireworks
Low and behold, as I'm scraping MSDN for every last bit of information I find a conflicting piece in the Win32 CryptExportKey function. Low and behold I find this piece of invaluble information:
So it does export a key that is a multiple of 64 bits! Woohoo! Now to fix the code on the .NET side.
.NET Import Code Tweak
The byte order is important to keep in mind when importing a byte stream that contains a key that was exported as a blob from the CryptoAPI. The two API's do not use the same byte order, therefore, as @nic-strong indicates, reversing the byte array is essential before actually trying to use the key. Other than that, things work as expected. Simply solved:
Conclusion
I hope this helps somebody out there. I spent way too much time trying to track this down. Leave any comments if you have further questions and I can attempt to help fill in any details.
Happy Crypto!