公钥令牌的作用是什么?它是否有任何解密签名哈希的部分。在GAC中,为什么Microsoft有这么多程序集具有相同的公钥令牌?
答案 0 :(得分:151)
公钥令牌的作用是什么?
公钥令牌是一个小数字,是表示公钥的方便的“令牌”。公钥很长;公钥令牌的目的是让你在不说出整个密钥的情况下引用密钥。类似的方式说“指环王”是五个词,代表一个半个字的小说。如果你每次想谈论它都会很不方便,你必须陈述那些五十万字。
它是否有任何解密签名哈希的部分?
没有。公钥令牌中没有“信息”。它只是一个代表公钥的数字。它本身不是公钥。
为什么Microsoft有这么多程序集使用相同的公钥令牌?
因为它们都使用相同的私钥(Microsoft的私钥)签名,因此都使用相同的公钥进行验证,因此所有私钥都具有相同的公钥令牌。
答案 1 :(得分:14)
“公钥标记用于使程序集名称唯一。因此,两个强名称程序集可以具有相同的PE文件名,但.NET会将它们识别为不同的程序集.Windows文件系统(FAT32和NTFS)只识别PE文件名,因此具有相同PE文件名(但文化,版本或公钥令牌不同)的两个程序集不能存在于同一个Windows文件夹中。为解决此问题,.NET引入了一种称为GAC(全局程序集缓存)的东西)它被.NET CLR视为单个文件夹,但实际上是使用嵌套的NTFS(或FAT32)文件夹实现的。
为了防止欺骗攻击,当一个破解者试图传递一个看起来像其他东西的程序集时,程序集会使用私钥进行签名。预期程序集的开发人员将私钥保密,因此破解者无法访问它,也不能简单地猜测它。因此,饼干不能使他的组件冒充别的东西,缺乏在改变后正确签名的可能性。对程序集进行签名涉及获取程序集的重要部分的哈希值,然后使用私钥加密哈希值。签名的哈希与公钥一起存储在程序集中。 公钥将解密签名的哈希值。当CLR加载一个强命名的程序集时,它将从程序集生成一个哈希值,然后将其与解密的哈希值进行比较。如果比较成功,则表示文件中的公钥(以及公钥标记)与用于对程序集签名的私钥相关联。这意味着程序集中的公钥是程序集发布者的公钥,因此挫败了欺骗攻击。 “
答案 2 :(得分:6)
哈希是一种“指纹”。它使用签名者拥有(并且仅为已知)的私钥进行签名。如果你知道签名者的公钥,你可以检查哈希是否真的来自签名者,因此数据/文件是否真的来自签名者(并且没有改变)。 GAC中某些文件的相同公钥表示“全部由同一签名者签名”。
答案 3 :(得分:5)
公钥标记是真实公钥的一些可读摘录。完整的公钥存储在已签名的程序集中,用于解密签名(=加密的哈希)。加载程序使用它来验证内容是否未被篡改(或损坏)。原始哈希值由作者使用私钥加密,只有拥有该密钥的人才能生成有效签名。
每个公司(或部门)只应使用1个密钥对,这就是您在GAC中看到相同PKT组的原因。
答案 4 :(得分:1)
我想补充之前的答案(特别是维基百科引用的答案),通过公钥/私钥进行的强命名不会保护您免于获得更改的程序集或阻止某人篡改您的程序集。
首先,强名称并不保证汇编可以信任。您只有一个公钥/公钥令牌,但您不知道签名的人(除非他们以某种方式宣布他们拥有程序集公钥)。
例如,黑客可以带你的程序集,从中删除强名称(有工具可以执行此操作),并使用自己的强名称对其进行签名。 对于信任,有一种不同类型的数字代码与证书签名。它涉及第三方检查您和您的公司,并不是免费的。查看Authenticode技术:
https://msdn.microsoft.com/en-us/library/ms537359(v=vs.85).aspx
其次,在下面的讨论中简要描述了一种暴力攻击方法,用于获取具有相同公钥令牌的公钥/私钥对,这将为篡改的程序集生成相同的哈希:
https://groups.google.com/forum/?hl=en#!topic/microsoft.public.dotnet.security/Jo6PqypxJN8
我必须注意到,这可以通过增强的强命名来解决 https://docs.microsoft.com/en-us/dotnet/framework/app-domains/enhanced-strong-naming
在讨论中还提到了一个错误,它允许跳过程序集的验证并在运行时加载一个篡改的程序集。详细的研究在这里,错误是在.Net框架的更高版本中修复的(因此旧的.Net 1存在错误):
http://www.grimes.nildram.co.uk/workshops/fusionWSCrackThree.htm
第三,默认情况下,对于完全信任程序集,启动.Net 3.5 sp1以提高程序集加载性能不会得到验证。
装配条件: https://blogs.msdn.microsoft.com/shawnfa/2008/05/14/strong-name-bypass/
关于Stack Overflow的讨论: Are signed .net assemblies ever fully verified when loaded, to check they haven't been modified?
据我所知,这意味着在加载过程中不会对程序集进行哈希处理,以检查它是否
最后,我想提一下有关强命名的优缺点的辩论,因为它们要求您指定汇编版本。微软从他们的一些产品中删除了强名称: https://www.pedrolamas.com/2016/03/01/still-strong-naming-your-assemblies-you-do-know-its-2016-right/
总之,我想总结所有提及的观点。当我遇到强烈的命名时,我被MSDN和维基百科误导,它可以为程序集提供某种防御。我认为“酷”,强烈的命名仍然留在我的记忆中作为保护机制。直到我不得不用私钥考虑我的snk文件的安全性,然后我的同事告诉我它不是那么“酷”。所以我做了一点研究。 我学到的第一件事是强名不代表信任,你应该使用证书。 尽管如此,我认为如果我保持私钥安全,那么被篡改的组件将不会被我签名,这意味着如果有人将修改我的程序集,那么他也必须修改标志,并且修改后的程序集将不会被加载CLR。现在我认为强有力的命名不能保证这一点。所以你应该只依靠它来保证装配的唯一性。
PS。很抱歉很长的帖子有很多参考。