开源项目中管理强名称密钥对的推荐方法是什么?

10

我管理一个开源项目,希望对发布在项目二进制包中的二进制文件进行签名。我使用Visual Studio的csprojsln文件来管理和构建我的项目,并将这些文件作为项目源代码包的一部分进行分发。

我如何对生成的二进制文件进行签名,而无需分发snk密钥对文件?如果我使用Visual Studio对程序集进行签名,则每个项目文件现在都需要密钥对的副本才能进行构建。即使密码受到保护,我也不放心分发密钥对。

编辑:

另一个限制是,项目中的某些程序集通过InternalsVisibleToAttribute授予了友元访问权限,并通过项目引用构建这些友元。因此,这些程序集需要使用强名称来引用已签名的程序集。但是,如果不分发密钥对,那么最终用户如何构建源代码并维护项目关系?如果使用临时密钥对文件,那么签名程序集的公钥令牌会改变,从而破坏InternalsVisibleToAttribute的引用?

3个回答

9
这是一个老问题,但目前得票最高的答案不准确,所以我认为值得发表新答案。
对于开源项目,Microsoft建议将您的私钥提交到存储库中。这是安全的,因为强名称密钥用于标识,而不是安全性。
参见此处的参考资料:https://learn.microsoft.com/en-us/dotnet/framework/app-domains/strong-named-assemblies 请注意以下引用:
不要依赖强名称进行安全性。它们仅提供唯一的标识。
他们还特别提到了开源项目:
如果你是一个开源开发者,并且你想要强命名程序集的身份验证好处,请考虑将与程序集相关联的私钥提交到您的源代码控制系统中。
如果您希望为程序集提供安全性,则应查看Authenticode签名:https://blogs.msdn.microsoft.com/shawnfa/2005/12/13/authenticode-and-assemblies/

6

不应分发密钥对。强名称用于验证程序集的新版本来自相同的发布者。

如果另一个开发人员想要将您的项目分支,他们将生成自己的密钥对,这将有效地显示他们的版本不是来自您,因此依赖于您的其他程序集将不再加载,除非它们被重新编译。这并不总是方便,但它可以保护您免受某人发布恶意程序集的威胁,并静默分发它。


由于我需要分发项目和解决方案文件,而且在启用签名时解决方案构建需要密钥对,那么我是否应该分发一个“虚拟”的密钥对,以便最终用户可以在不必操作项目文件的情况下进行构建?看起来很麻烦,需要检入禁用签名的项目文件,然后每次发布时都要切换此设置。 - Steve Guidi
3
您可以执行以下操作:添加一个构建步骤,检查是否已存在 .snk 文件,并在必要时运行 sn.exe 生成一个新的 .snk 文件。这样其他用户就可以直接从代码库中进行构建。 - sharptooth
确保发布者身份不是强名称签名的预期目的。您应该使用Authenticode来完成这项任务。Microsoft自己的文档建议发布SNK文件: https://learn.microsoft.com/en-us/dotnet/standard/assembly/strong-named?redirectedfrom=MSDN - ahelwer

2
如果代码中的唯一程序集引用是在项目文件中编码的,则Sharptooth's solution 的方法可行。如果您的项目通过 InternalsVisibleToAttribute 或其他需要强名称字符串的方式引用其他程序集,则使用临时密钥构建存储库源代码将不可行。这样做会更改存在于强名称字符串中的公钥引用并破坏代码。
这是我应用程序的情况,因此我需要采用不同的方法。
我基本上在单独的文件夹层次结构中创建了一个 slncsproj 文件的副本,并按如下方式修改了 csproj 文件。
  • 将所有文件引用转换为链接,指向原始源。
  • 复制和修改每个 AssemblyInfo.cs 文件,以包含使用带有强名称的 InternalsVisibleToAttribute
  • 修改每个 csproj 文件,使 snk 文件引用为相对路径(去除了将 snk 文件复制到每个项目的需要)
我首先手动完成了所有这些操作,但后来意识到可以以简单明了的方式自动化这个过程。第一步和第三步可以使用 XSLT 实现,而第二步可以使用正则表达式搜索/替换函数实现。
由于我现在需要维护两个解决方案,因此自动化此任务是有意义的,以避免未来的麻烦。
存储库中的源代码不构建具有强名称的程序集,这很好,因为我不想对最终用户施加任何构建限制或流程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接