从 sn.exe 实用程序的描述和这个问题中,我看到公钥的副本被添加到使用强名称签名的每个程序集中。这足以验证程序集二进制文件没有被更改。
但是如何验证给定的程序集确实是用给定的密钥对签名并由给定的公司编译的呢?任何人都可以生成自己的密钥对,生成一些程序集并用他的密钥对进行签名。我是否需要发布公钥,以便那些想要验证程序集来源的人可以比较公钥?如果是这样,最好的方法是什么?
从 sn.exe 实用程序的描述和这个问题中,我看到公钥的副本被添加到使用强名称签名的每个程序集中。这足以验证程序集二进制文件没有被更改。
但是如何验证给定的程序集确实是用给定的密钥对签名并由给定的公司编译的呢?任何人都可以生成自己的密钥对,生成一些程序集并用他的密钥对进行签名。我是否需要发布公钥,以便那些想要验证程序集来源的人可以比较公钥?如果是这样,最好的方法是什么?
不,您不需要在程序集之外发布您的公钥,因为它被散列并作为令牌存储在客户端应用程序内的引用旁边:
AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07"
这提供了一种方法来确保程序集的所有未来版本都针对相同的密钥对进行编译,因此来自相同的发布者。
有关如何获取此信息阻止其他来源假装您的更多详细信息,请参阅我的其他答案。
我一直理解签署程序集的目的是作为运行时检查,以确保对代码的升级来自受信任的来源。实际上,他们正试图避免这种情况:
我从 A 公司购买了一个加密库,不久之后,B 公司获得了我的电子邮件详细信息,并向我发送了一个免费升级到该程序集,假装是 A 公司的一个重大安全错误修复程序,当它真正向我的代码中注入了一个隐藏的方法时将我试图加密的所有数据发送到 B 公司的服务器。假设我是个白痴,并且盲目地将这个新的 dll 添加到我的应用程序的 bin 目录中,那么它没有使用与旧版本相同的私钥签名的事实将在运行时被拾取,从而导致异常并保护我的数据。
因此,我认为您没有理由在程序集之外发布公钥,因为它不应该保证原始文件来自特定供应商,只是所有后续版本都来自与第一个版本相同的位置。
维基百科说了很多同样的话(只是用更少的词)。
编辑以添加更多信息,以使这一点更清晰......
我认为首先需要澄清的是公钥和私钥对是唯一的。这意味着知道公钥不足以重建程序集以使其通过相同的哈希检查。
因此,用户 Z 正在使用公司 A 的加密库,该加密库位于他的应用程序 bin 文件夹中。为此,他按如下方式引用 DLL:
Encryption, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07"
公钥的目的是为我们提供三个好处,我将一次处理一个。
首先,它为程序集提供了一个唯一的名称——这没有给我们额外的安全性,但确实阻止了 C 风格的 dll 地狱,两家不同的公司可以发布两个不同的库,称为 Encyption 版本 1.0.0.0,而你将无法将它们存储在相同的目录,因为没有办法区分它们。
其次,它阻止了我在原始帖子中概述的场景。B 公司不可能创建另一个版本的加密库,它也是 1.0.0.0 版本并且具有相同的公钥(这样整个名称就会匹配,并且您会调用他们的代码而不是 A 公司的代码)。他们不能这样做,因为如果他们的公钥匹配,那么私钥也必须匹配(因为每一对 都是唯一的)。他们可以让私钥匹配的唯一方法是破坏 A 公司的安全性。
最后,它确保文件的完整性(通过损坏或恶意代码注入进行更改)。dll 在运行时(当它是私有的并且在应用程序的 bin 文件夹中时)或安装时(当您将其放入 GAC 时)使用公钥进行哈希处理,并将该哈希值与私有加密的哈希值进行比较密钥并存储在程序集中。这个页面有一些图表和更多细节。再次伪造这个散列的唯一方法是知道私钥。
因此,为了涵盖我上面描述的特定场景,假设我是 B 公司,试图向用户 Z 提供加密 dll 的恶意版本。我的第一次尝试是简单地使用名称加密和版本 1.0.0.0 制作我自己的 dll,并使用我自己的密钥对对其进行签名。不幸的是,我无法更改用户 Z 应用程序中的参考代码,因此它无法通过全名检查并且不会被加载。“好吧,”我一边捻着小胡子一边说,“我将简单地更改我的程序集的公钥以匹配 A 公司的公钥。” 完成此操作后,名称检查通过,但哈希检查将失败,因为用户 Z 的应用程序将无法使用公钥(公司A's) 已提供。因此,B 公司创建伪装成 A 公司的库的唯一方法是知道 A 公司的私钥。这些安全检查都不依赖于 A 公司在其他任何地方发布公钥,但在程序集的原始版本中。
另请注意,所有这些功能都不能确保(也不声称确保)原始程序集来自 A 公司,由Verisign或 Microsoft 的Authenticode服务等其他系统处理,它们仅确保一旦您拥有引用了该程序集,只有 A 公司可以更改该代码。
摘要:
您不仅验证了代码没有被修改过,而且还使用您信任的一方颁发的证书进行了签名。