C# 公钥令牌的作用是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1321419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:07:43  来源:igfitidea点击:

What is the role of public key token?

c#.net

提问by devnull

What is the role of public key token? Does it have any part in decrypting the signed hash. In GAC, why is there so many assemblies from Microsoft with the same public key token?.

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

采纳答案by Eric Lippert

What is the role of public key token?

公钥令牌的作用是什么?

The public key token is a small number which is a convenient "token" representing a public key. Public keys are quite long; the purpose of the public key token is to let you refer to keys without saying the whole key. Sort of the same way saying "The Lord of the Rings" is five words which representa half-a-million-word novel. It would be rather inconvenient if every time you wanted to talk about it, you had to state those half-a-million words.

公钥令牌是一个很小的数字,它是代表公钥的方便“令牌”。公钥很长;公钥令牌的目的是让您在不说整个密钥的情况下引用密钥。类似的说法“指环王”是五个字,代表一部五十万字的小说。如果每次要谈的时候,都得说出那五十万个字,那会很不方便。

Does it have any part in decrypting the signed hash?

它在解密签名散列方面有任何作用吗?

No. The public key token has no "information" in it. It's just a number that representsa public key. It is not itself a public key.

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

why are there so many assemblies from Microsoft with the same public key token?

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

Because they were all signed with the same private key -- Microsoft's private key -- and are therefore all verified with the same public key, and therefore all have the same public key token.

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

回答by ur.

The hash is kind of a "finger print". It is signed using a private key owned (and only known) by the signer. If you know the public key of the signer, you can check if the hash is really from the signer and thus if the data/file really originates from the signer (and is unchanged). Same public keys for some files in the GAC mean "all signed by the same signer".

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

回答by rism

From Wikipedia

来自维基百科

"The public key token is used to make the assembly name unique. Thus, two strong named assemblies can have the same PE file name and yet .NET will recognize them as different assemblies. The Windows file system (FAT32 and NTFS) only recognizes the PE file name, so two assemblies with the same PE file name (but different culture, version or public key token) cannot exist in the same Windows folder. To solve this issue .NET introduces something called the GAC (Global Assembly Cache) which is treated as a single folder by the .NET CLR, but is actually implemented using nested NTFS (or FAT32) folders.

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

To prevent spoofing attacks, where a cracker would try to pass off an assembly appearing as something else, the assembly is signed with a private key. The developer of the intended assembly keeps the private key secret, so a cracker cannot have access to it nor simply guess it. Thus the cracker cannot make his assembly impersonate something else, lacking the possibility to correctly sign it after the change. Signing the assembly involves taking a hash of important parts of the assembly and then encrypting the hash with the private key. The signed hash is stored in the assembly along with the public key. The public key will decrypt the signed hash.When the CLR loads a strongly named assembly it will generate a hash from the assembly and then compare this with the decrypted hash. If the comparison succeeds then it means that the public key in the file (and hence the public key token) is associated with the private key used to sign the assembly. This will mean that the public key in the assembly is the public key of the assembly publisher and hence a spoofing attack is thwarted. "

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

回答by Henk Holterman

The Public Key Token is a somewhat readable excerpt of the real public key. The complete public key is stored inside a signed assembly and is used to decrypt the signature (= encrypted hash). The loader uses this to verify the contents are not tampered with (or damaged). The original hash was encrypted by the author using a private key and only someone in possession of that key can produce a valid signature.

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

Each company (or department) should only use 1 key-pair, that is why you see groups of identical PKT's in the GAC.

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

回答by SENya

I would like to add to the previous answers (especially to the one with the quote from Wikipedia) that the strong naming via public/private key doesn't protect you from getting a changed assembly or prevent someone from tampering with your assemblies.

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

First of all, strong name doesn't guarantee that assembly can be trusted. You just have a public key/public key token, but you don't know the person who signed it (except if they somehow announce that they own the assemblies public key).

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

For example, the hacker could take yours assembly, remove strong name from it (there are tools which do it), and sign it with its own strong name. For the trust there is a different kind of digital code signing with the certificate. It involves third party checking you and your company and is not free. Check out Authenticode technology:

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

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

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

Secondly, In the following discussion briefly described a brute force attack method to get public/private key pair with the same public key token which would produce the same hash for a tampered assembly:

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

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

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

I must note that this could have been addressed by the enhanced strong naming https://docs.microsoft.com/en-us/dotnet/framework/app-domains/enhanced-strong-naming

我必须注意,这可以通过增强的强命名来解决 https://docs.microsoft.com/en-us/dotnet/framework/app-domains/enhanced-strong-naming

There were also a bug mentioned in the discussion which allowed to skip the validation of assembly and load a tampered assembly at runtime. The detailed research is here, the bug was fixed in the later versions of .Net framework(so the bug present for the old .Net 1):

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

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

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

Thirdly, starting the .Net 3.5 sp1 to increase the performance of the load of the assemblies are not validated by default for full trust assemblies.

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

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

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

The condition for assemblies: https://blogs.msdn.microsoft.com/shawnfa/2008/05/14/strong-name-bypass/

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

The discussion about it on Stack Overflow: Are signed .net assemblies ever fully verified when loaded, to check they haven't been modified?

Stack Overflow 上关于它的讨论:已 签名的 .net 程序集在加载时是否经过完全验证,以检查它们是否未被修改?

As I understand, this means that assembly is not hashed during load to check if it

据我了解,这意味着在加载期间不会对程序集进行散列以检查它是否

Lastly, I would like to mention that there is a debate about pros and cons of strong naming since they require that you specify an assembly version. Microsoft removes strong name from some of their products: https://www.pedrolamas.com/2016/03/01/still-strong-naming-your-assemblies-you-do-know-its-2016-right/

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

In conclusion, I wanted to summarize all of the mentioned points. When I encountered strong naming I was misguided by the MSDN and Wikipedia that it could provide some sort of defense for the assemblies. I thought "Cool" and the strong naming remained in my memory as a protection mechanism. Until the moment I had to think about the safety of my snk file with private key and then my colleague told me that it's not so "Cool". So I did a little research. The first thing I learned was that strong name doesn't mean trust, you should use the certificate for it. Still, I thought that if I keep my private key safe then the tampered assembly won't be signed by me, meaning that if someone will modify my assembly then he has to modify the sign too and the modified assembly won't be loaded by the CLR. Now I don't think that strong naming guarantees that. So you should rely on it only to guarantee the uniqueness of the assembly.

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

PS. Sorry for the long post with a lot of references.

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