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

时间:2020-03-05 18:49:11  来源:igfitidea点击:

我有一个用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不会使用相同的字节顺序,因此,正如@ n​​ic-strong所指出的,在实际尝试使用密钥之前,反转字节数组是必不可少的。除此之外,一切都按预期进行。简单解决:

Array.Reverse( keyByteArray );

总结

我希望这可以帮助某人。我花了太多时间试图找到答案。如果我们还有其他问题,请留下任何评论,我会尽力填写任何详细信息。

快乐加密!