【问题标题】:What is the role of public key token?公钥令牌的作用是什么?
【发布时间】:2010-11-22 05:27:25
【问题描述】:

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

【问题讨论】:

  • @Bombe,解密签名哈希是正确的,只有 1 个错误。
  • 如果您熟悉 SSH 或 PGP,这就是您所知道的指纹,即。公钥的缩短版本,更易于肉眼检查。

标签: c# .net


【解决方案1】:

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

【讨论】:

  • 所以令牌只是使用的 pub 密钥的指示符吗?它不直接参与加密/解密
【解决方案2】:

来自Wikipedia

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

为了防止欺骗攻击,即破解者会试图假冒以其他方式出现的程序集,该程序集使用私钥进行签名。预期程序集的开发者将私钥保密,因此破解者无法访问它,也无法简单地猜测它。因此,破解者不能让他的程序集冒充其他东西,在更改后无法正确签名。对程序集进行签名涉及获取程序集重要部分的哈希,然后用私钥加密哈希。签名的哈希与公钥一起存储在程序集中。 公钥将解密签名的哈希。 当 CLR 加载强命名程序集时,它将从程序集生成哈希,然后将其与解密的哈希进行比较。如果比较成功,则意味着文件中的公钥(以及公钥令牌)与用于签署程序集的私钥相关联。这意味着程序集中的公钥是程序集发布者的公钥,因此欺骗攻击被阻止。 "

【讨论】:

    【解决方案3】:

    公钥令牌是真正的公钥的一些可读的摘录。完整的公钥存储在签名程序集中,用于解密签名(= 加密哈希)。加载程序使用它来验证内容没有被篡改(或损坏)。原始哈希由作者使用私钥加密,只有拥有该密钥的人才能生成有效签名。

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

    【讨论】:

      【解决方案4】:

      公钥令牌的作用是什么?

      公钥令牌是一个小数字,是代表公钥的方便“令牌”。公钥很长;公钥令牌的目的是让您在不说整个密钥的情况下引用密钥。有点像“指环王”的说法是五个词,代表一部五十万字的小说。如果每次你想讲它,都得把那五十万字说出来,那就很不方便了。

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

      没有。公钥令牌中没有“信息”。它只是一个代表公钥的数字。它本身不是公钥。

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

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

      【讨论】:

      • 埃里克的回答多么清晰而完美!
      • @Ammar 通过代码检查Assembly.FullName 属性,要通过命令行工具获取它,请参阅this answer
      【解决方案5】:

      我想补充一下之前的答案(尤其是引用维基百科的答案),通过公钥/私钥进行强命名并不能保护您免受更改的程序集或防止有人篡改您的程序集.

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

      例如,黑客可以获取您的程序集,从中删除强名称(有一些工具可以这样做),然后用自己的强名称对其进行签名。 对于信任,证书有不同类型的数字代码签名。它涉及第三方检查您和您的公司,并且不是免费的。查看 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://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/

      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 和 Wikipedia 误导,认为它可以为程序集提供某种防御。我认为“酷”和强大的命名作为一种保护机制留在我的记忆中。直到我不得不用私钥考虑我的 snk 文件的安全性,然后我的同事告诉我这不是那么“酷”。所以我做了一点研究。 我学到的第一件事是强名称并不意味着信任,您应该使用证书。 尽管如此,我认为如果我保持我的私钥安全,那么被篡改的程序集将不会由我签名,这意味着如果有人要修改我的程序集,那么他也必须修改签名并且修改后的程序集不会被加载CLR。现在我认为强命名不能保证这一点。所以你应该只依赖它来保证程序集的唯一性。

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

      【讨论】:

        猜你喜欢
        • 2012-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-16
        • 2011-09-23
        • 2021-11-01
        • 2021-11-27
        • 2010-09-21
        相关资源
        最近更新 更多