如何在我的.NET应用程序中使用Win32 CryptoAPI生成的密钥blob?

时间:2008-09-08 05:42:23

标签: .net c++ encryption cryptography cryptoapi

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

问题是我们如何在.NET应用程序(C#)中使用它。该框架封装/包装了CryptoAPI正在做的大部分内容。部分问题是CryptAPI声明Microsoft Enhanced Cryptographic Provider的TripleDES算法是168位(56位的3个密钥)。但是,.NET框架声明它们的密钥是192位(64位的3个密钥)。显然,.NET框架中的3个额外字节用于奇偶校验?

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

更新

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

2 个答案:

答案 0 :(得分:5)

简介

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

先决条件

为了使其中的许多内容有意义,有必要阅读exponent of one trick,它允许您将会话密钥导出到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端的密钥。可行,但不是很有趣......让我们离开吧。一旦我完成了所有这些工作,一切都以资本 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 );

结论

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

Happy Crypto!

答案 1 :(得分:1)

好的,忘了我读不懂的最后一个答案:)你正在使用3Des键而不是RSA键。

我在一堆代码上工作,在.NET,CryptoAPI和openssl之间共享密钥。在这里找到了许多用于进行密钥转换的优秀示例代码:

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

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

我还回顾了RSA密钥代码,我注意到我正在做的一件事是在RSA密钥的所有关键部分使用Array.Reverse()(D,DP,DQ,InverseQ,模数,P, Q)我想转换结束。我记得在第一次解决问题时不明显。

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