如何在.NET应用程序中使用从Win32 CryptoAPI生成的密钥Blob?
我有一个用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中使用该密钥时,我们没有得到预期的结果。解密失败了。任何帮助将不胜感激。
更新:
我一直在研究解决此问题的方法,并提出了一个解决方案,我将及时发布该解决方案。但是,仍将感谢其他人的任何反馈。
解决方案
回答
好的,忘记我看不懂的最后一个答案了:)我们正在使用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()猜测要转换字节序。我记得第一次解决问题时并不太明显。
希望其中的一些帮助。祝你好运。
回答
介绍
我终于可以发布解决方案了。我希望它可以为其他可能在做类似类型事情的人提供一些帮助。实际上,在其他地方没有太多参考。
准备工作
为了使很多事情变得有意义,有必要阅读一个技巧的指数,该技巧使我们可以将会话密钥导出到Blob(众所周知的字节结构)中。然后,可以使用此字节流执行他们希望的操作,但是它拥有所有重要的密钥。
MSDN文档令人困惑
在此特定示例中,我使用带有三重DES(CALG_3DES)算法的Microsoft增强加密提供程序。让我循环的第一件事是,密钥长度列出为168位,块长度为64位。密钥长度如何为168?三个56位的键?另一个字节会怎样?
因此,借助这些信息,我开始在其他地方阅读最后一个字节是如何真正实现奇偶校验的,并且无论出于何种原因,CryptoAPI都会将其删除。真的是这样吗?他们似乎会这样做有些疯狂,但是可以。
.NET中的密钥消耗
通过使用TripleDESCryptoServiceProvider,我注意到文档中的注释表明:
This algorithm supports key lengths from 128 bits to 192 bits in increments of 64 bits.
因此,如果CryptoAPI的密钥长度为168,我如何将其输入仅支持64的倍数的.NET?因此,API的.NET端考虑了奇偶校验,而CryptoAPI则没有考虑。可以想象...我很困惑。
因此,通过所有这些,我试图找出如何使用适当的奇偶校验信息在.NET端重建密钥。可行,但不是很有趣...让我们就这样吧。一旦所有这些都准备就绪,一切都会以CAPITAL F失败。
还在我这儿?好,因为我又摔下来了。
灯泡和烟花
低估了,因为我要抓取MSDN的每一个最后信息,所以我在Win32 CryptExportKey函数中发现了一个冲突的部分。低估,我发现这条宝贵的信息:
For any of the DES key permutations that use a PLAINTEXTKEYBLOB, only the full key size, including parity bit, may be exported. The following key sizes are supported. Algorithm Supported key size CALG_DES 64 bits CALG_3DES_112 128 bits CALG_3DES 192 bits
因此,它确实会导出64位倍数的密钥! oo!现在在.NET端修复代码。
.NET导入代码调整
导入包含从CryptoAPI作为blob导出的密钥的字节流时,请记住字节顺序,这一点很重要。这两个API不会使用相同的字节顺序,因此,正如@ nic-strong所指出的,在实际尝试使用密钥之前,反转字节数组是必不可少的。除此之外,一切都按预期进行。简单解决:
Array.Reverse( keyByteArray );
总结
我希望这可以帮助某人。我花了太多时间试图找到答案。如果我们还有其他问题,请留下任何评论,我会尽力填写任何详细信息。
快乐加密!