公钥令牌的作用是什么?

公钥令牌的作用是什么? 它有没有解密签名散列的任何部分? 在GAC中,为什么有这么多来自Microsoft的程序集使用相同的公钥令牌?

公钥令牌的作用是什么?

公钥标记是一个很小的数字,这是一个代表公共密钥的方便的“标记”。 公钥很长, 公钥标记的目的是让你不用说整个密钥就可以引用密钥。 “指环王”是用五个词来代表一个五十万字的小说。 如果每次想谈论这个问题,你都必须陈述那五十万字。

它有解密签名散列的任何部分?

公钥标记没有“信息”。 这只是一个代表公钥的数字。 它本身不是一个公钥。

为什么有这么多来自微软的程序集使用相同的公钥令牌?

因为它们都使用相同的私钥(Microsoft的私钥)进行签名,因此都使用相同的公钥进行validation,因此它们都具有相同的公钥令牌。

从维基百科

“公共密钥令牌用于使程序集名称唯一,因此,两个强有名的程序集可以具有相同的PE文件名,而.NET将它们识别为不同的程序集,Windows文件系统(FAT32和NTFS)只能识别PE文件名,所以具有相同的PE文件名(但不同的文化,版本或公共密钥令牌)的两个程序集不能存在于同一个Windows文件夹中。为了解决这个问题,.NET引入了GAC(全局程序集caching)被.NET CLR视为单个文件夹,但实际上是使用嵌套的NTFS(或FAT32)文件夹实现的。

为了防止欺骗攻击,一个破解者会试图将一个程序集看作是别的东西,程序集是用私钥签名的。 预定程序集的开发人员将私钥保密,所以黑客不能访问它,也不能简单地猜测它。 因此,黑客不能让他的集会冒充别的东西,在改变之后缺乏正确签署的可能性。 对程序集签名包括对程序集的重要部分进行散列,然后用私钥对散列进行encryption。 签名散列与公钥一起存储在程序集中。 公钥将解密已签名的散列。 当CLR加载一个强命名的程序集时,它将从程序集生成一个哈希,然后将其与解密的哈希进行比较。 如果比较成功,则意味着文件中的公钥(以及公钥标记)与用于签署程序集的私钥相关联。 这将意味着程序集中的公钥是程序集发布者的公钥,因此欺骗攻击受挫。 “

哈希是一种“指纹”。 它使用签名者拥有的(并且只有已知的)私钥进行签名。 如果您知道签名者的公钥,那么您可以检查哈希是否真的来自签名者,因此如果数据/文件真的源自签名者(并且不变)。 GAC中某些文件的公用密钥意思是“全部由同一个签名者签名”。

公钥标记是真实公钥的可读摘录。 完整的公钥存储在一个签名的程序集中,用于解密签名(encryption哈希)。 加载程序使用它来validation内容是否被篡改(或损坏)。 原始散列是由作者使用私钥encryption的,只有拥有该密钥的人才能生成有效签名。

每个公司(或部门)只能使用1个密钥对,这就是为什么您在GAC中看到一组相同的PKT。

我想补充以前的答案(尤其是维基百科的引用),通过公钥/私钥强命名不会保护您不会受到更改的程序集或防止有人篡改您的程序集。

首先 ,强名不能保证程序集是可信的。 你只是有一个公钥/公钥标记,但你不知道谁签名(除非他们以某种方式宣布他们拥有程序集公钥)。

例如,黑客可以把你的程序集合起来,从中删除强大的名字(有工具可以做),并用自己的强名称来签名。 对于信任,有一种不同的数字代码与证书签名。 它涉及第三方检查你和你的公司,并不是免费的。 检查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

在讨论中还提到了一个bug,它允许跳过程序集的validation并在运行时加载被篡改的程序集。 详细的研究在这里,错误是在.Net框架的后续版本中解决的(所以旧的.Net 1中存在的错误):

http://www.grimes.nildram.co.uk/workshops/fusionWSCrackThree.htm

第三 ,启动.net 3.5 sp1以提高程序集加载的性能未完全信任程序集默认进行validation。

https://docs.microsoft.com/en-us/dotnet/framework/app-domains/how-to-disable-the-strong-name-bypass-feature

程序集的条件: https : //blogs.msdn.microsoft.com/shawnfa/2008/05/14/strong-name-bypass/

关于堆栈溢出的讨论: 签名的.net程序集在加载时经过了充分的validation,检查它们没有被修改?

据我所知,这意味着在装载过程中不会对散列进行散列检查

最后 ,我想提一下,由于需要指定程序集版本,因此有强烈的命名利弊的争论。 Microsoft从其某些产品中删除了强名称: https : //www.pedrolamas.com/2016/03/01/still-strong-naming-your-assemblies-you-do-know-its-2016-right/

总之 ,我想总结所有提到的观点。 当我遇到强大的命名时,我被MSDN和Wikipedia误导了,它可以为程序集提供某种防御。 我认为“酷”,强大的命名作为保护机制留在我的记忆中。 直到现在我不得不用私钥考虑我的snk文件的安全性,然后我的同事告诉我,它不是那么“酷”。 所以我做了一点研究。 我学到的第一件事就是强名不意味着信任,你应该使用它的证书。 不过,我想如果我保证我的私钥安全,那么被篡改的程序集将不会被我签名,这意味着如果有人会修改我的程序集,那么他也必须修改标志,修改后的程序集将不会被加载CLR。 现在我不认为强大的命名保证。 所以你只能靠它来保证assembly的独特性。

PS。 对不起,有很多引用的长篇文章。