公钥令牌的作用是什么?


79

公钥令牌的作用是什么?它在解密签名哈希中是否有任何作用?在GAC中,为什么会有这么多来自Microsoft的具有相同公钥令牌的程序集?


1
@Bombe,解密签名哈希将是正确的,只有1个错误。
亨克·霍尔特曼


如果您熟悉SSH或PGP,则将其称为指纹。公钥的简化版本,更易于通过眼睛进行检查。
恐慌上校

Answers:


160

公钥令牌的作用是什么?

公钥令牌是一个很小的数字,是表示公钥的方便的“令牌”。公钥很长;公钥令牌的目的是让您引用密钥而不用说整个密钥。用同样的方式说“指环王”是五个单词,代表一部五十万字的小说。如果每次您想谈论它时,都必须说出五十万个单词,那将是非常不便的。

它在解密签名哈希中有任何作用吗?

否。公钥令牌中没有“信息”。这只是代表公钥的数字。它本身不是公共密钥。

为什么会有这么多具有​​相同公钥令牌的Microsoft程序集?

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


3
埃里克真是个酥脆而完美的答案!
Aditya Bokade 2014年

@Ammar通过代码检查Assembly.FullName属性,通过命令行工具获取它,请参见此答案
Scott Chamberlain

14

来自维基百科

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

为了防止欺骗攻击,在这种情况下,破解者会试图假冒其他出现的程序集,并使用私钥对程序集进行签名。预定程序集的开发人员将私钥保密,因此,破解者无法访问它,也不能简单地猜测它。因此,破解者无法使他的程序集模仿其他内容,缺少在更改后正确签名的可能性。对程序集进行签名涉及对程序集重要部分进行哈希处理,然后使用私钥对哈希进行加密。签名的哈希值与公钥一起存储在程序集中。公钥将解密签名的哈希。当CLR加载一个强命名的程序集时,它将从该程序集生成一个哈希,然后将其与解密的哈希进行比较。如果比较成功,则意味着文件中的公钥(以及公钥令牌)与用于对程序集进行签名的私钥相关联。这将意味着程序集中的公钥是程序集发布者的公钥,因此将阻止欺骗攻击。”


6

哈希是一种“指纹”。使用签名者拥有(且仅是已知的)私钥对它进行签名。如果您知道签名者的公钥,则可以检查哈希是否确实来自签名者,从而检查数据/文件是否确实源自签名者(并且未更改)。GAC中某些文件的相同公共密钥意味着“全部由同一签名者签名”。


所以令牌只是所使用的pub键的指示器吗?它不直接参与加密/解密
Softwarematter

5

公钥令牌是真实公钥的某种可读性摘录。完整的公共密钥存储在已签名的程序集中,并用于解密签名(=加密的哈希)。加载程序使用它来验证内容没有被篡改(或损坏)。作者使用私钥对原始哈希进行加密,只有拥有该密钥的人才能产生有效的签名。

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


1

我想补充一下以前的答案(尤其是来自Wikipedia的引用),通过公钥/私钥的强命名并不能保护您免受更改的程序集的影响,也不能防止他人篡改您的程序集。

首先,强名并不能保证程序集可以被信任。您只有一个公共密钥/公共密钥令牌,但您不知道签名的人(除非他们以某种方式宣布自己拥有程序集的公共密钥)。

例如,黑客可以将您的程序集带走,从中删除强名称(有工具可以执行此操作),然后使用自己的强名称对其进行签名。为了获得信任,证书上还有另一种数字代码签名。它涉及第三方检查您和您的公司,并且不是免费的。查看Authenticode技术:

https://msdn.microsoft.com/zh-CN/library/ms537359(v=vs.85).aspx

其次,在下面的讨论中,简要描述了一种蛮力攻击方法,该方法使用相同的公钥令牌获取公钥/私钥对,这将为被篡改的程序集产生相同的哈希值:

https://groups.google.com/forum/?hl=zh-CN#!topic/microsoft.public.dotnet.security/Jo6PqypxJN8

我必须注意,增强的强命名功能可以解决此问题, https://docs.microsoft.com/zh-cn/dotnet/framework/app-domains/enhanced-strong-naming

讨论中还提到了一个错误,该错误允许跳过程序集的验证并在运行时加载被篡改的程序集。详细的研究在这里,该错误已在.NET Framework的更高版本中修复(因此,该错误适用于旧版.Net 1):

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

第三,默认情况下,对于完全信任程序集,不启动.Net 3.5 sp1以提高程序集负载的性能。

https://docs.microsoft.com/zh-cn/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程序集在加载时是否经过过完全验证,以检查它们是否已被修改?

据我了解,这意味着程序集不会在加载过程中进行散列检查

最后,我想提一提,关于强命名的利弊之争,因为它们要求您指定程序集版本。微软从其某些产品中删除了强名:https : //www.pedrolamas.com/2016/03/01/still-strong-naming-your-assemblies-you-do-know-its-2016-right/

结论,我想总结所有提到的要点。当我遇到强命名时,我被MSDN和Wikipedia误导了它可能为程序集提供某种防御。我认为“酷”和强烈的命名仍然保留在我的记忆中,作为一种保护机制。直到此刻,我不得不考虑带有私钥的snk文件的安全性,然后我的同事告诉我,它并不是那么“酷”。所以我做了一些研究。我了解到的第一件事是,强名并不意味着信任,因此应该使用证书。尽管如此,我还是认为,如果我保持私钥的安全,那么被篡改的程序集将不会被我签名,这意味着如果有人修改了我的程序集,那么他也必须修改符号,并且修改后的程序集将不会被加载CLR。现在我不 认为强大的命名可以保证这一点。因此,您应仅依靠它来保证组件的唯一性。

PS。很抱歉,这篇长篇文章有很多参考资料。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.