我有一个用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中使用密钥时没有得到预期的结果。解密失败了。任何帮助将不胜感激。
我一直在努力解决这个问题,并提出了一个我将及时发布的解决方案。但是,仍然会感谢来自其他人的任何反馈。
答案 0 :(得分:5)
我终于开始发布解决方案了。我希望它能为那些可能做类似事情的人提供一些帮助。在其他地方真的没有太多提及这一点。
为了使其中的许多内容有意义,有必要阅读exponent of one trick,它允许您将会话密钥导出到blob(一个众所周知的字节结构)。然后可以用这个字节流做他们想做的事情,但它拥有所有重要的密钥。
在这个特定的例子中,我正在使用Microsoft Enhanced Cryptographic Provider,使用Triple DES(CALG_3DES)算法。抛弃循环的第一件事是密钥长度以168位列出,块长度为64位。钥匙长度怎么样168? 56位的三个键?另一个字节会发生什么?
所以有了这些信息,我开始在其他地方读到最后一个字节是如何真正的奇偶校验,无论出于何种原因,CryptoAPI将其剥离。那是真的吗?看起来有点疯狂,他们会那样做,但是好的。
使用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端的代码。
在导入包含从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)我想转换结束。我记得在第一次解决问题时不明显。
希望其中一些有帮助。祝你好运。