.NET 3.5加密实现和Mono 2.x实现的区别是什么?

3

我有一份相同的代码在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会抛出"Bad Data"异常。
我尝试过:
- 不同的.NET设置(3.5最小值,AnyCPU / x86 / x64) - 不同的密钥(一些会抛出异常,一些不会,但是当我验证它们时,.NET签名总是无效的,而使用相同密钥和消息生成的Mono签名却正常工作)
是否存在一些根本性的差异,导致MS DSA实现和Mono的实现方式有所不同?
更多信息:
- 密钥在Java中生成,并在转换为DER格式以与.NET兼容后进行导出 - 使用BinaryReader从磁盘加载密钥,并将整数值加载为byte []到DSAParameters(P,Q,G和X)中 - 公钥在Java应用程序中加载,该应用程序使用Oracle实现来验证签名 - 所有C#代码都是“对称”的,即在Mono和MS .NET应用程序中使用相同
更新2:
今天早上我再次尝试了一下,同样的.NET应用程序在Mac上运行(使用Mono Develop,普通香草),在Windows上运行(Visual Studio 2010)。加载相同的私钥字节,相同的代码路径(至少就C#而言)——只有在Windows上才会出现“bad data”异常。以下是密钥:
P: 17801190547854226652823756245015999014523215636912067427327445031444286578873
70207706126952521234630795671567847784664499706507709207278570500096683881440341
29745221171818506047231150039301079959358067395348717066319802262019714966524135
060945913707594956514672855690606794135837542707371727429551343320695239

Q: 864205495604807476120572616017955259175325408501

G: 17406820753240209518581198012352343653860449079456135097849583104059995348845
58231478515974089409507253077970949157594923683005742524387610370844734671801488
76118103083043754985190983472601550494691329488083395492313850000361646482644608
492304078721818959999056496097769368017749273708962006689187956744210730

X: 3505625379966178555918512548923624458026758122

...


我用.NET和mono做了一些快速的健全性检查,没有发现任何问题。我注意到一个无效的“Seed”属性可能会导致“坏数据”错误,但我也希望在mono中能够出现这种情况。更多的信息可能有所帮助:(1)您是如何生成私钥的(例如,在.NET或mono的“DSACryptoServiceProvider”中之一)?(2)您能否提供更多代码(例如,用于加载“DSAParameters”的代码,也许问题就在那里)。(3)您说.NET签名始终无效,您是如何验证它们的? - softwariness
@softwariness 我已经更新了我的问题并提供了更多信息。具体来说:1)密钥不是在.NET中生成的,而是在Java中生成的;2)加载代码完全相同,并且当我对生成的原始私钥字节进行逐字节比较时,在使用ImportParameters加载它们之前,它们是完全相同的 - SonarJetLens
Java和Mono代码运行在哪个操作系统和架构上?我想知道问题是否是字节序错误。 - softwariness
Java代码可以在Linux和Windows上运行(已经测试过)。.NET代码(Mono和MS)都可以在PC上运行(对于Mono部分,还可以在Mac上运行),因此,考虑到无论平台如何,Mono->Java路径都可以正常工作,这似乎不是一个字节序问题。特别是在加载之前,原始字节是相同的。我开始怀疑MS .NET是否有一些规则,用于隐藏某些DSA所允许使用的整数...这有意义吗? - SonarJetLens
2
我实际上是在考虑Mono与.NET实现的DSACryptoServiceProvider中的字节序问题,而不是从文件加载参数时的字节序(即进入ImportParameters的字节相同,但被该方法解释不同),但这可能并不是原因。关于.NET限制值,这是有可能的,或者它可能是一个错误。您能否提供一些示例参数的十六进制或base64格式,这些参数无法导入到.NET中,以便我尝试复现它? - softwariness
@softwariness,周一回到办公室后我会这样做,计划不错。 - SonarJetLens
2个回答

1

这个问题已经有一段时间了,而且项目已经朝着非常不同的方向发展,但是你的建议似乎很合理。如果我再次找到这个项目,我会尝试这个方法来确认。 - SonarJetLens

0

简短的回答是,哈希码可能会因为不同的.NET Framework版本和平台(例如32位和64位平台),或者Microsoft和Mono之间的差异而有所不同。

可以在这里阅读更多信息: Object.GetHashCode ,请查看备注。

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

从文档中我了解到,DSACryptoServiceProvider是一种非对称的加密方式,它使用哈希来创建数字签名。这是链接: DSACryptoServiceProvider Class ,请查看备注。


但是使用的哈希算法将是SHA1,它不依赖于对象哈希码(因为这是字节序列的哈希,而不是对象),对吧? - SonarJetLens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接