在 GitHub 和 NuGet 上发布的项目中,我应该如何指定强名称键的路径?

Posted

技术标签:

【中文标题】在 GitHub 和 NuGet 上发布的项目中,我应该如何指定强名称键的路径?【英文标题】:How should I specify the path to the strong name key in projects published on GitHub and NuGet? 【发布时间】:2022-01-10 22:13:40 【问题描述】:

我不是在问强名称密钥的路径在哪里。这应该是显而易见的。 我问的是路径表达式应该是什么样子,我几乎了解操作系统路径规范的所有内容。

GitHub 项目是一个 Visual Studio 2022 解决方案,由 20 多个 .NET 6.0 C# 项目组成。大多数项目旨在作为单独的 NuGet 包发布。

除了这些,细节。

密钥的路径应该放在项目文件中。 这是我的担忧: 我可以指定 2 种路径:绝对路径和相对路径。当我移动我的项目时,亲戚会破裂。当我移动键时,绝对值会中断。

当我更改驱动器号时,"D:\Source\Keys\MyKey.snk" 等绝对路径也会中断,Windows 会为可移动驱动器分配不同的驱动器号等。

除非我通过像"\Source\Keys\MyKey.snk" 这样的路径。如果只有 Visual Studio 允许它工作,它似乎是最优雅和最好的解决方案。但事实并非如此。我猜它会将其解析为"C:\Source\Keys\MyKey.snk",因为如果它安装在"C:\..." 中,为什么不呢。

所以,要么是带有驱动器号的丑陋路径,要么是丑陋的相对路径。 我的确切问题是有第三种选择吗?也许是 IDK,使用环境变量、Visual Studio 配置的内部变量或类似的东西?

现在我坚持相对路径。然后还有一个问题。 如果有人拉 GitHub 项目,它不会编译抱怨缺少的键。当然,他们可以删除程序集签名,然后它就可以工作了。

还有其他方法吗?

所以我的 GitHub 项目的当前状态是“默认强名称/相对键路径”,它允许我在推送或发布代码更改时专注于编码,而不会分心。但是如果有更好的密钥解决方案,我只是好奇。

【问题讨论】:

【参考方案1】:

推荐:签入强名称键

.NET 团队为库作者提供以下文档,其中包含专门关于强命名的页面:https://docs.microsoft.com/dotnet/standard/library-guidance/strong-naming

这部分是相关的:

考虑将强命名密钥添加到您的源代码控制系统。

公开可用的密钥允许开发人员使用相同的密钥修改和重新编译您的库源代码。

如果过去曾使用强命名密钥在部分信任场景中授予特殊权限,则不应公开它。否则,您可能会损害现有环境。

重要

当需要代码发布者的身份时,推荐使用 Authenticode 和 NuGet 包签名。代码访问安全 (CAS) 不应用作安全缓解措施。

关于强名称的此页面也相关:https://docs.microsoft.com/dotnet/standard/assembly/strong-named

警告

不要依赖强名称来保证安全。它们仅提供唯一身份。

因此,强名称密钥与安全性无关,因此如果您将其提交到源代码控制中,应该不会有任何真正的风险。如果你想要安全,那就是 Authenticode 的用途,它使用不同的密钥。

替代方案:PublicSign

还有另一个功能PublicSign,它通过延迟签名程序集解决了 .NET Framework 上的信任问题。但老实说,这与只签入整个强名称密钥并没有太大区别,因为它需要您提交公钥。

首先,使用sn.exe to extract just the public key(快速浏览一下,我认为它是-p 选项)。注意这个文档页面也有警告说强名称不是安全的。无论如何,这样任何人都可以在他们的本地机器上构建您的代码,并且它会生成一个具有相同身份的程序集,允许他们将本地构建的副本放入自己的应用程序中作为替换,并且一切都应该正常工作。

不推荐:CI 和本地构建的工作方式不同

如果由于某种原因您不会签入强名称密钥,那么您应该将构建配置为在本地运行时与在 CI 中运行时不同。与软件开发中的大多数事情一样,您可以通过多种方式实现这一目标,您自己的创造力是限制因素。

一种方法是将项目文件配置为不对程序集进行签名,然后在运行 sn.exe 的 CI 脚本中单独执行一个步骤来对程序集进行签名。但是,即使您只有一个 ProjectReference,这也会增加复杂性。

另一种方法是利用 MSBuild 是一种编程语言这一事实​​,尽管它看起来像一个声明性 XML 文件。 <SignAssembly Condition=" '$(StrongNameKey)' != '' ">true</SignAssembly> 之类的东西,不要在项目文件中提交 <StrongNameKey> 属性。更改您的 CI 构建以使用 dotnet build -p:StrongNameKey=c:\full\path\to\sn.snk

但是,这意味着任何在本地构建您的库的开发人员都无法生成与您分发的二进制文件兼容的替代二进制文件。如果有人发现并修复了错误,并希望在等待您接受上游错误修复时使用他们自己的副本,他们将不得不重新编译所有使用您的包的程序集,以确保他们都使用相同的不同身份比你的二进制文件。如果他们使用使用您的包的第 3 方程序集,那么他们将处于非常困难的境地,因为他们还必须重新编译所有这些程序集以使用您的程序集的本地构建版本,只是因为您没有提供强名称键。

【讨论】:

谢谢好心的陌生人!我应该做我的功课并自己找到,但有时我只是想不清楚......所以我会在 GitHub 上发布密钥,如果推荐的话。我的本地构建有点不同 - 唯一的区别是它使用本地依赖项进行 Debug 配置而不是包依赖项。对于Release,它使用包。如果我必须在测试之前发布每个依赖项,那将是一场噩梦。我做这样的测试,但只有当Debug 测试通过时。 NuGet 会在打包项目时自动将 ProjectReferences 转换为包依赖项。您不需要在本地与 CI/Release 构建不同地构建您的解决方案。 所以当我不发布依赖项目时 - 它将被内置到依赖包中,但是当我发布依赖项目时它会使用已发布的包作为依赖项? NuGet 有那么聪明吗? 我不明白这个问题,但这也与原始问题无关。我只是建议你玩一玩,看看事情是如何运作的。例如:dotnet new console -n MyApp; dotnet new classlib -n MyLib1; dotnet new classlib -n MyLib2; dotnet add MyApp reference MyLib1; dotnet add MyLib1 reference MyLib2; dotnet new sln; dotnet sln add MyApp; dotnet sln add MyLib1; dotnet sln add MyLib2; dotnet pack。查看生成的 nupkg 以查看它们是否与您尝试执行的操作具有相似的关系/依赖关系。项目也可以配置为不可打包。

以上是关于在 GitHub 和 NuGet 上发布的项目中,我应该如何指定强名称键的路径?的主要内容,如果未能解决你的问题,请参考以下文章

Github自动打包并推送Nuget包

Github自动打包并推送Nuget包

持续集成配置之Nuget

NuGet - RID和TFM示例

NuGet 包还原 + NuGet 源设置

具有托管依赖项的C ++ / XAML UWP NuGet包