C#:为啥要签署程序集?
Posted
技术标签:
【中文标题】C#:为啥要签署程序集?【英文标题】:C#: why sign an assembly?C#:为什么要签署程序集? 【发布时间】:2011-04-27 21:43:15 【问题描述】:在我接管的一些 C# 代码中(在 Visual Studio 2005 中),我注意到程序集都使用相同的 .snk
文件签名。
【问题讨论】:
【参考方案1】:如果要将程序集放在GAC 中,则需要对其进行签名。
如果您对可执行文件进行签名,则它链接到的任何类库也需要进行签名。如果您使用第三方库(尤其是需要使用ActiveX 控件或类似控件时),这可能会很困难。
Richard Grimes 在.NET 写了一个关于安全性的很好的研讨会,其中包括一个关于此的章节:Security Workshop
使用同一个 .snk 文件对所有程序集进行签名的原因可能是他使用了带有代码覆盖率的单元测试。为了能够进行代码覆盖(至少使用 Visual Studio 2005 测试版本中内置的工具)并且如果程序集已签名,您需要指定用于签名的 .snk 文件,但我认为您只能为整个解决方案指定一个 .snk 文件,因此如果您使用不同的 .snk 文件对各种类库进行签名,则一次只能检查其中一个的代码覆盖率。
【讨论】:
【参考方案2】:为什么以前的作者会以这种方式签署程序集?
不知道,也许他希望他的所有程序集都使用相同的密钥进行签名。
是否需要对程序集进行签名,不签名会有什么问题?
不,这不是必需的,但它是一种机制,可让您确保程序集的真实性。它允许您确保程序集没有被篡改,并且确实来自该作者。如果您想将它们放入 GAC,这也是必要的。
签署程序集有什么缺点 - 会导致延迟吗?
签名程序集只能加载其他签名程序集。它们还与特定版本相关联,这意味着如果您想使用不同的版本,您需要使用绑定重定向或重新编译应用程序。由于签名的验证,还有一点性能开销,但它太小了,您不必担心。
【讨论】:
请注意,在 GAC 中不再进行签名验证(从 .NET 2.0 开始); it only happens once, when adding it to the GAC. 你觉得现在签署它怎么样?在基于 Web 的系统上?如果我是正确的,只有在谈论已安装的软件时才有必要,对吧?如果我使用 TFS 将我的应用程序发布到 Azure,我知道它没有被篡改,对吗?还是我错过了一些安全部分? 关于第一个问题:他从一个具有程序集签名密钥文件的项目中制作了项目模板,然后他使用该项目模板创建了另一个东西并忘记替换密钥文件。 (只需将“他”替换为“我”,你就知道我今天早上在做什么了 :))。所以,这是偶然的。【参考方案3】:签署程序集的一个非常重要的原因是您可以确定它是您的程序集。由于私钥是您的,因此没有其他人可以使用相同的密钥签署程序集。这意味着,当程序集的公钥是您知道的(您可以使用GetType().Assembly.GetName().GetPublicKey()
函数检索它)时,程序集就是您的并且没有被篡改。
【讨论】:
【参考方案4】:尽管有签名 dll 的所有用法,但应仅出于两个原因对 dll 进行签名
1.版本控制
2。身份验证
一个。版本控制表示构建 dll 的版本,在将它们推送到 GAC 时,可以存在两个同名但版本不同的 dll
b.身份验证表示dll是否未被篡改,并且在创建时是否存在。
如果您想了解更多有关基础知识和 dll 签名的信息,可以参考here
【讨论】:
你觉得现在签署它怎么样?在基于 Web 的系统上?如果我是正确的,只有在谈论已安装的软件时才需要,对吧?如果我使用 TFS 将我的应用程序发布到 Azure,我就知道它没有被篡改,对吗?还是我遗漏了一些安全部分? 我看不出我们现在应该签署一个 dll 的理由,它将被部署为 azure 中的 Paas 解决方案。但是如果你有 iaas 解决方案,你可能会在同一个 iis 中通过 web 应用程序重用 dll。我不推荐。我们应该通过 api url 调用它们,而不是使用 GAC(微服务架构)中的那些 dll。【参考方案5】:除了现有答案之外,我还要补充一点,当您的 DLL 将被第 3 方软件动态加载和使用时,您必须使用签名。这本身不是技术要求,但出于安全考虑,第三方软件生产商执行此类策略是合理的,因此非常普遍。
必须签署程序集的示例:
开发 Windows Shell / Windows Explorer 扩展,例如:Windows Explorer 的上下文菜单扩展 开发 Visual Studio 扩展,例如:项目/项目模板向导 GUI【讨论】:
【参考方案6】:签名和组装很重要。 为了确保只安装在该 PC 上的 exe 或程序集。
即:如果您复制该文件夹并放入另一台 PC,则它不起作用。因为它只是将该程序集登录到那台机器上。
【讨论】:
【参考方案7】:请原谅我回答了一个老问题。但是这里的大多数响应都暗示强命名提供了安全性。但微软建议不要将其用于安全性。
关于强名称签名的文档目前说:
⚠警告
不要依赖强名称来保证安全。它们仅提供唯一身份。
它主要用于确保您拥有预期的二进制文件,而不是偶然具有相同名称和版本(或通过绑定重定向设置的版本)的不同二进制文件
微软列出了使用强命名的原因:
您希望您的程序集能够被强名称程序集引用,或者您希望朋友可以从其他强名称程序集访问您的程序集。 应用程序需要访问同一程序集的不同版本。这意味着您需要不同版本的程序集在同一个应用程序域中并排加载而不会发生冲突。例如,如果 API 的不同扩展存在于具有相同简单名称的程序集中,则强命名会为程序集的每个版本提供唯一标识。 您不想对使用您的程序集的应用程序的性能产生负面影响,因此您希望程序集是域中立的。这需要强命名,因为必须在全局程序集缓存中安装与域无关的程序集。 您希望通过应用发布者策略来集中为您的应用提供服务,这意味着程序集必须安装在全局程序集缓存中。
它还指出:
对于 .NET Core,强名称程序集不提供实质性好处。
和
如果您是一名开源开发人员,并且希望获得强名称程序集的身份优势以更好地与 .NET Framework 兼容,请考虑将与程序集关联的私钥签入到您的源代码控制系统。
因此,Microsoft 表示可以将您的强命名私钥与代码一起发布。这意味着任何人都可以使用正确的公钥创建强名称程序集。我会说可以安全地假设强命名不是真实性的安全来源。
在此处了解更多信息:https://docs.microsoft.com/en-us/dotnet/standard/assembly/strong-named
【讨论】:
如果您需要安全检查 SignTool.exe docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe 和 docs.microsoft.com/en-us/windows/win32/seccrypto/…以上是关于C#:为啥要签署程序集?的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使在添加程序集“Microsoft.SqlServer.ConnectionInfo”之后 C# 也无法识别 Server()
使用 pfx 和 Visual Studio 签署具有强名称的程序集