2009-04-28 55 views
5

从sn.exe实用程序的描述和this question我看到公钥的副本被添加到每个使用强名称签名的程序集中。这足以验证程序集二进制文件没有被修改。我是否需要从.snk文件发布公钥?

但是,我们如何验证给定的程序集是否真的用给定的公钥进行了签名?任何人都可以生成自己的密钥对,生成一些程序集并用他的密钥对签名。我是否需要发布公钥,以便那些想验证程序集来源的人可以比较公钥?如果是的话,最好的办法是什么?

回答

5

不,你没有需要发布的组件外部的公共密钥,因为它是散列和令牌沿着客户端的应用程序内的参考存储:

AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07" 

这给出了一个方法来确保该程序集的所有将来版本都是针对相同的密钥对进行编译的,因此也是来自同一个发布者。

有关的更多详细信息如何拥有此信息阻止假装成为您的另一个来源可以在我的其他答案中找到。

3

我一直都明白将程序集签名为运行时检查的目的,以确保代码的升级来自可信来源。他们有效地试图避免这种情况:

我从A公司购买了一个加密库,不久之后公司B得到了我的电子邮件详细信息,并且向我发送了一个免费升级程序,假装它是一个重大的安全漏洞当A公司真的向我的代码中注入隐藏的方法时发现公司A的修复,这些代码将我试图加密到B公司服务器的所有数据发送出去。假设我是一个白痴,并盲目地将这个新的dll添加到我的应用程序的bin目录中,事实上这不是与旧版本相同的私钥签名,将在运行时被选中导致异常并保护我的数据。

因此,我没有理由认为你会在程序集之外发布公钥,因为它不能保证原始文件来自特定的供应商,只是所有后续版本都来自相同的地方首先。

Wikipedia说了很多相同的事情(只有在明显更少的词)。


编辑补充,企图使之更清楚的详细信息...

我认为,需要澄清的第一件事是,公钥和私钥的对是唯一的。这意味着知道公钥是没有足够的信息来重建程序集的方式,它将通过相同的散列检查。

因此,用户Z正在使用位于其应用程序bin文件夹中的公司A的加密库。要做到这一点,他被引用的DLL如下:

Encryption, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07" 

公钥的目的是为我们提供three benefits,我会处理一次一个。

首先,它为程序集提供了一个唯一的名称 - 这不会给我们带来额外的安全性,但会停止C风格的DLL地狱,两家不同的公司可能会发布两个不同的库,名为Encyption版本1.0.0.0,您将无法将它们存储在相同的目录中,因为没有办法区分它们。其次,它阻止了我在原始文章中列出的场景。公司B不可能创建另一版本的Encryption库,该版本也是1.0.0.0版本,并且具有相同的公钥(这样整个名称将匹配,并且您将调用其代码而不是公司A)。他们不能这样做,因为如果他们的公钥匹配,那么私钥也必须匹配(因为每个是唯一的)。他们能够得到私钥的唯一方法就是通过损害公司A的安全性。

最后它确保文件的完整性(通过损坏或恶意代码注入进行更改)。该DLL在运行时(当它是私有的,在应用程序的bin文件夹中)或安装时间(当你将它放入GAC中)使用公钥进行散列,并将该散列与由私有文件编译的散列进行比较键并存储在程序集中。 This page有一些图表和更多细节。再次伪造这个散列的唯一方法是知道私钥。

因此,为了覆盖上面描述的特定场景,假设我是B公司试图向用户Z提供恶意版本的加密dll。我的第一个尝试是简单地制作我自己的dll名称为Encryption和Version 1.0.0.0,并用我自己的密钥对进行签名。不幸的是,我无法更改用户Z的应用程序中的参考代码,因此无法进行全名检查,也无法加载。 “好吧,”我一边捻着胡须一边说,“我只是简单地改变我的大会的公钥,使其与公司A的公钥相匹配”。一旦我完成了这个操作,名称检查就会通过,但散列检查将失败,因为用户Z的应用程序将无法使用公钥(公司B)对解密存储在程序集中的散列(使用公司B的私钥加密) A's)。因此,B公司创建一个伪装成A公司的图书馆的唯一方法就是了解A公司的私钥。这些安全检查都不依赖于公司A在其他任何地方发布公钥,而是在程序集的原始版本中发布公钥。

还请注意,所有这些功能都不能保证(不要求保证),其原装配来自A公司,由其他系统如Verisign或微软的Authenticode服务处理,他们只保证一旦您引用了程序集,只有公司A可以对该代码进行更改。

+0

这完全不清楚,没有在链接的文章中明确提及。为了做到这一点,运行时需要缓存每个程序集的散列值,并验证加载程序集时的情况。它真的这么做吗? – sharptooth 2009-04-29 04:14:45

+1

根据Jeffery Richter的“CLR via C#”,它在程序集不在GAC中时执行。从书中引用:“当从GAC以外的位置加载强命名的程序集时,CLR会在加载程序集时比较哈希值,换句话说,每次应用程序执行并加载程序集时都会执行该文件的哈希。这种性能影响是确保程序集文件的内容没有被篡改的折衷。“ – 2009-04-29 07:48:48

2
  1. 你可以去一些3D方证书提供者(例如VeriSign)并从他们那里购买证书(Code Signing At Verisign)。
  2. 您使用指定的证书,其上有您的公司名称,URL等来签署您的代码。
  3. 我下载你的应用程序,并查看你的应用程序签署的证书列表。
  4. 我使用您的证书,返回VeriSign并验证证书确实已发给MyCompany,LLC。
  5. 我查看用于颁发证书的证书,并验证VeriSign是否是其中的一个(Windows带有少量安装的可信证书)。

摘要:
你不仅验证码尚未修修补补用,而且不同之处是由您信任的一方颁发的证书签名。

相关问题