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

How should I specify the path to the strong name key in projects published on GitHub and NuGet?

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

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

有了这些东西,细节。

密钥的路径应放在项目文件中。 这是我的担忧: 我可以指定两种路径:绝对路径和相对路径。当我移动我的项目时,亲戚会崩溃。当我移动钥匙时,绝对会坏掉。

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

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

中,为什么不呢?

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

现在我坚持使用相对路径。那么还有一个问题。 如果有人拉 GitHub 项目,它不会编译抱怨丢失的键。当然,他们可以删除程序集签名,这样就可以了。

还有其他方法吗?

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

推荐:签入强名称密钥

.NET 团队为库作者提供了以下文档和指南,其中有一个专门介绍强命名的页面:https://docs.microsoft.com/dotnet/standard/library-guidance/strong-naming

这部分是相关的:

CONSIDER adding the strong naming key to your source control system.

A publicly available key lets developers modify and recompile your library source code with the same key.

You shouldn't make the strong naming key public if it has been used in the past to give special permissions in partial-trust scenarios. Otherwise, you might compromise existing environments.

Important

When the identity of the publisher of the code is desired, Authenticode and NuGet Package Signing are recommended. Code Access Security (CAS) should not be used as a security mitigation.

有关强名称的页面也很重要:https://docs.microsoft.com/dotnet/standard/assembly/strong-named

Warning

Do not rely on strong names for security. They provide a unique identity only.

因此,强名称密钥与安全无关,因此如果您只是将其提交给源代码管理,就不会有任何真正的风险。如果你想要安全,这就是 Authenticode 的用途,它使用不同的密钥。

备选方案:PublicSign

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

首先,使用sn.exe to extract just the public key(快速查看,我认为是-p选项)。请注意此文档页面还有警告说强名称不安全。不管怎样,这样任何人都可以在他们的本地机器上构建你的代码,它会生成一个具有相同标识的程序集,允许他们放入本地构建的副本作为他们自己应用程序中的替代品,一切都应该正常工作。

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

如果出于某种原因您不会签入强名称密钥,那么您应该将构建配置为在 运行 本地时与 运行 在 [=48= 中时不同地工作].与软件开发中的大多数事情一样,实现这一点的方法几乎没有限制,您自己的创造力是限制因素。

一种方法是将您的项目文件配置为不对程序集进行签名,然后在 CI 脚本中有一个单独的步骤 运行s sn.exe 对程序集进行签名。但是,如果您只有一个 ProjectReference.

,这将增加复杂性

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

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