【问题标题】:Difference between .NET 3.5 Cryptography implementation and Mono 2.x implementation?.NET 3.5 Cryptography 实现和 Mono 2.x 实现之间的区别?
【发布时间】:2015-03-13 15:11:14
【问题描述】:

我在 Mono (Unity 4.5) 和 MS .NET 下编译和运行相同的代码:

DSAParameters privateKey;
...
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(csp);
dsa.PersistKeyInCsp = false;
dsa.ImportParameters(privateKey);

在 Mono 和 MS .NET 版本中,私钥是从磁盘加载的,并且正在加载的字节和设置的整数在“privateKey”中是相同的。

在 .NET 版本中,dsa.ImportParameters 抛出“Bad Data”异常。

我试过了

  • 不同的 .NET 设置(最低 3.5,AnyCPU/x86/x64)
  • 不同的键 (有些抛出,有些没有,但 .NET 签名总是(?) 当我验证它们时无效,而使用 Mono 中相同的键和相同的消息可以正常工作。)

MS DSA 的实现方式和 Mono 的实现方式之间是否存在一些根本的潜在差异,这可能会导致这种情况..?

欢迎任何光棚...这有点让人头疼...

更多信息:

  • 密钥在 Java 中生成,并在从 DER 格式转换为与 .NET 一起使用后导出(P1363;只是一个接一个的大整数)
  • 使用 BinaryReader 从磁盘加载密钥,并将整数值作为 byte[] 加载到 DSAParameters(P、Q、G 和 X)中
  • 公钥加载到 Java 应用程序中,该应用程序使用 Oracle 实现来验证签名
  • 所有 C# 代码都是“对称的”,即在 Mono 和 MS .NET 应用程序中按原样使用。

更新 2

好吧,我不会发疯的;今天早上我又试了一次;相同的 .NET 应用程序在 Mac 上运行(使用 Mono Develop,普通香草)和一个在 Windows 上(Visual Studio 2010)。 加载相同的私钥字节,相同的代码路径(至少就 C# 而言) - 仅在 Windows 上出现相同的“坏数据”异常。这是关键:

P: 17801190547854226652823756245015999014523215636912067427327445031444286578873
70207706126952521234630795671567847784664499706507709207278570500096683881440341
29745221171818506047231150039301079959358067395348717066319802262019714966524135
060945913707594956514672855690606794135837542707371727429551343320695239

Q: 864205495604807476120572616017955259175325408501

G: 17406820753240209518581198012352343653860449079456135097849583104059995348845
58231478515974089409507253077970949157594923683005742524387610370844734671801488
76118103083043754985190983472601550494691329488083395492313850000361646482644608
492304078721818959999056496097769368017749273708962006689187956744210730

X: 3505625379966178555918512548923624458026758122

...

【问题讨论】:

  • 我对 .NET 和 mono 进行的一些快速健全性检查没有发现任何问题。我确实注意到无效的Seed 属性可能会导致“错误数据”错误,但我也希望单声道也会出现这种情况。更多信息可能会有所帮助:(1)您如何生成私钥(例如,在 .NET 或单声道的 DSACryptoServiceProvider 中的一个或另一个中)? (2) 您能否提供更多代码(例如,用于加载DSAParameters 的代码,也许问题就在那里)。 (3) 你说.NET签名总是无效的,你是怎么验证的?
  • @softwariness 我用更多信息更新了我的问题。所以,特别是; 1) 密钥不是在 .NET 中生成,而是在 Java 中生成 2) 加载代码完全相同,当我对生成的原始私钥字节进行逐字节比较时,它们在我之前完全相同使用 ImportParameters 加载它们
  • Java 和 mono 代码运行在什么操作系统和架构上?我想知道问题是否是错误的字节顺序。
  • Java 代码在 Linux 和 Windows 上运行(均经过测试) - .NET 代码(Mono 和 MS)都在 PC(和 Mac,对于 Mono 部分)上运行,因此,鉴于 Mono->Java无论平台如何,路径都可以工作,这似乎不是字节顺序问题。特别是因为原始字节在加载之前是相同的。我开始怀疑 MS .NET 是否有某种规则,可以让您将哪些整数用于 DSA,这些整数隐藏在某个地方……这有意义吗?
  • 我实际上是在考虑 DSACryptoServiceProvider 的 Mono vs .NET 实现中的字节序,而不是从文件中加载参数(即进入 ImportParameters 的字节是相同的,但该方法的解释不同),但可能并非如此。 Re .NET 限制值,这是可能的,或者它可能是一个错误。您能否提供一些无法导入 .NET 的示例参数的 hex 或 base64,以便我可以尝试重现它?

标签: c# unity3d mono cryptography dsa


【解决方案1】:

.NET Framework 期望保持一些大小关系:

  • 问:20 个字节
  • G:与 P 长度相同
  • Y,如果存在:与 P 相同的长度
  • 种子(如果存在):20 个字节
  • X,如果存在:20 字节

这些只是底层加密提供者的传递要求:https://msdn.microsoft.com/en-us/library/windows/desktop/aa381987(v=vs.85).aspx#PRIVK_BLOB。

根据上述值的长度,您可能需要用零填充 X。

【讨论】:

  • 自从这个问题以来已经有一段时间了,该项目已经朝着一个非常不同的方向发展,但你的建议似乎是合理的。如果我设法再次挖掘该项目,我会尝试确认。
【解决方案2】:

简短的回答是,.NET Framework 版本和平台之间的哈希码可能不同,例如 32 位和 64 位平台;或者在微软和 Mono 之间。

可以在这里阅读: Object.GetHashCode,阅读备注。

我之前在 Unity3D 中开发跨平台多人游戏时遇到过这种情况。因此,您需要使用自己的哈希函数,或使用对称算法来加密您的数据。

从文档中我了解到 DSACryptoServiceProvider 本质上是不对称的,并且使用哈希来创建数字签名。链接在这里: DSACryptoServiceProvider Class,阅读备注。

【讨论】:

  • 但是使用的哈希算法将是 SHA1,它不依赖于对象哈希码(无论如何都不会使用,因为这是字节序列的哈希,而不是对象) ...对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-01
  • 1970-01-01
  • 2016-06-18
  • 2014-05-25
  • 2020-09-01
  • 2020-08-14
  • 2012-11-15
相关资源
最近更新 更多