C# NET 3.5加密实现和Mono 2.x实现之间的区别?

C# NET 3.5加密实现和Mono 2.x实现之间的区别?,c#,unity3d,mono,cryptography,dsa,C#,Unity3d,Mono,Cryptography,Dsa,我在Mono(Unity 4.5)和MS.NET下编译和运行了相同的代码: DSAParameters privateKey; ... DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(csp); dsa.PersistKeyInCsp = false; dsa.ImportParameters(privateKey); 私钥是从磁盘加载的,“privateKey”中加载的字节和设置的整数在Mono和MS.NET版本中是相同

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

DSAParameters privateKey;
...
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(csp);
dsa.PersistKeyInCsp = false;
dsa.ImportParameters(privateKey);
私钥是从磁盘加载的,“privateKey”中加载的字节和设置的整数在Mono和MS.NET版本中是相同的

在.NET版本中,dsa.ImportParameters引发“坏数据”异常

我试过了

  • 不同的.NET设置(最低3.5,AnyCPU/x86/x64)
  • 不同的键 (有些抛出,有些不抛出,但.NET签名总是(?) 验证时无效,而使用 在Mono中,相同的键和相同的消息可以正常工作。)
MS DSA的实现方式与Mono在引擎盖下的工作方式之间是否存在一些根本性的根本区别,这可能会导致这种情况

任何灯光都是最受欢迎的…这有点让人头疼

更多信息:

  • 该密钥是用Java生成的,在从DER格式转换为.NET格式后导出(P1363;只是一个接一个的大整数)
  • 使用BinaryReader从光盘加载密钥,并将整数值作为字节[]加载到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 Framework版本和平台之间的哈希代码可能不同,例如32位和64位平台;或者在微软和Mono之间

这里可以看到: ,阅读备注

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

从文档中,我了解到DSACryptoServiceProvider本质上是不对称的,它使用散列来创建数字签名。以下是链接:
,请阅读备注。

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

  • Q:20字节
  • G:和P一样长
  • Y、 如果存在:与P相同的长度
  • 种子,如果存在:20字节
  • 十、 如果存在:20字节
这些只是底层加密提供程序的传递要求:


根据上述值的长度,您可能需要在X上留下零。

我使用.NET和mono进行的一些快速检查没有发现任何问题。我确实注意到无效的
Seed
属性可能会导致“坏数据”错误,但我也希望mono也会出现这种情况。更多信息可能会有所帮助:(1)您是如何生成私钥的(例如,在.NET或mono的一个或另一个
DSACryptoServiceProvider
)?(2) 您能否提供更多的代码(例如,用于加载
dsapaparameters
,可能存在问题)。(3) 你说.NET签名总是无效的,你如何验证它们?@Softwarnese我已经用更多信息更新了我的问题。因此,具体而言;1) 密钥不是在.NET中生成的,而是在Java中生成的2)加载代码是完全相同的,当我对生成的原始私钥字节进行字节-字节比较时,它们在使用ImportParameters加载它们之前是完全相同的Java和mono代码运行在什么操作系统和体系结构上?我想知道问题是否出在endianness上。Java代码在Linux和Windows上运行(都经过测试)-.NET代码(Mono和MS)都在PC上运行(对于Mono部分,Mac也是如此),因此,考虑到Mono->Java路径在任何平台下都能正常工作,这似乎不是endianness问题。特别是因为原始字节在加载之前是相同的。我开始怀疑MS.NET是否有一些规则,它允许您使用哪些隐藏在某处的整数来进行DSA…这有意义吗?实际上,我想的是DSACryptoServiceProvider的Mono vs.NET实现中的endianness,而不是从文件中加载参数(即进入
ImportParameters
的字节相同,但该方法的解释不同),但这可能不是.Re.NET限制值,这是可能的,也可能是一个bug。您能否提供一些未能导入.NET的示例参数的十六进制或base64,以便我尝试复制它?但使用的哈希算法将是SHA1,它不依赖于对象哈希代码(反正也不用,因为这是字节序列的散列,不是对象)…对吗?这个问题和项目已经有一段时间没有朝着完全不同的方向发展了,但你的建议似乎是合理的。如果我能再次挖掘这个项目,我会尝试验证一下。