C# 如何以编程方式验证程序集是否使用特定证书签名?
我的设想是,如果在特定文件夹中找到一个程序(exe),它将启动其他程序。我想确保它只启动使用我们的公司证书(Verisign approved等)签名的程序。从本质上讲,它将只使用与自身相同的证书启动程序。我不想把证书寄出去 我一直在搜索web和系统名称空间,但没有找到一个清晰的示例,可以从文件中读取证书数据并对其进行验证,还可以对照另一个文件进行检查。我发现最接近的是Signtool,在一个单独的exe中进行验证是没有意义的。我知道强命名的东西不会有帮助,因为数字签名的文件是不同的,这里有帮助地解释了这一点(http://blog.codingoutloud.com/2010/03/13/three-ways-to-tell-whether-an-assembly-dl-is-strong-named/)还有一些其他示例显示了原始数据的加密和验证,但不是以某种方式打包在一起的程序集C# 如何以编程方式验证程序集是否使用特定证书签名?,c#,.net,digital-certificate,assembly-signing,C#,.net,Digital Certificate,Assembly Signing,我的设想是,如果在特定文件夹中找到一个程序(exe),它将启动其他程序。我想确保它只启动使用我们的公司证书(Verisign approved等)签名的程序。从本质上讲,它将只使用与自身相同的证书启动程序。我不想把证书寄出去 我一直在搜索web和系统名称空间,但没有找到一个清晰的示例,可以从文件中读取证书数据并对其进行验证,还可以对照另一个文件进行检查。我发现最接近的是Signtool,在一个单独的exe中进行验证是没有意义的。我知道强命名的东西不会有帮助,因为数字签名的文件是不同的,这里有帮助
有什么想法或建议吗?有两种用于.NET程序集的签名技术:strong命名和Authenticode(Authenticode用于对PE和其他一些文件进行签名,而不仅仅是.NET程序集)。它们用于不同的目的。在Authenticode中,证书仅用于对作者进行身份验证。strong命名根本不对作者进行身份验证 除了检查签名外,还必须验证证书,以确保它是为给定的作者颁发的。正确的验证是一个复杂的过程,涉及CRL(证书吊销列表)和OCSP(在线证书状态)检查 要执行Authenticode签名验证,您需要Authenticode验证组件。其中一个选项是使用我们的SecureBackbox产品包。该软件包包括Authenticode验证以及完整的证书验证机制
请注意,如果您不打算验证证书,那么验证签名就毫无意义,因为您可以创建具有相同主题、序列号等的自签名证书,并使用它对伪造的程序集进行签名 您可以在这里尝试三个选项 1) 第一个是使用程序集加载,如下所示:
Assembly myDll =
Assembly.Load("myDll, Version=1.0.0.1, Culture=neutral, PublicKeyToken=9b35aa32c18d4fb1");
可以使用以下强名称(Sn.exe)命令打印特定程序集的公钥和公钥令牌的十六进制格式:
sn-Tp。并使用p/Invoke处理此类问题
3) 还有第三种更灵活、更复杂的方法。这是一个具有约束力的策略。当您需要为已部署的应用程序提供升级时,您可以考虑这一点。当您的应用程序可以从共享组件的新版本中受益时,应用程序策略文件将允许您提供这些好处,而无需重新编译或更换现有安装
您可以在此处找到有关此功能的更多信息:
下面是一篇关于如何验证程序集签名的代码示例的博文:
最后的代码示例演示了如何验证程序集是否由Microsoft签名-您可以通过获取公司证书的证书令牌来执行相同的操作
更新:user@Saber使用以下更新编辑了此更新,但该更新被其他人拒绝。但是,这是一个非常有效的建议,因此我将重新发布他/她的编辑,因为so不允许我批准:
编辑(谢谢,OP):如果您想更安全地执行此操作(即使您的程序更防篡改),请引用程序中使用相关密钥强命名的程序集,然后使用引用程序集的标记与调用程序集的标记进行比较。如果您使用字节数组(根据链接),它可以简单地进行十六进制编辑和更改。我相信有一种方法可以使用强名称来达到“信任”的目的。我知道Microsoft只建议使用强名称以确保程序集内容未被修改,并建议使用“Authenticode”以获得信任
但是如果加载器应用程序(加载这些程序集/程序的应用程序)维护一个可以加载的“程序集”的加密列表;这难道不能解决“信任”问题吗
例如,包加载器可以使用公钥维护程序集名称,并通过完整的程序集名称加载程序集/程序
<PackageHandlers>
<PackageHandler>
<Package type="Package1" assembyName="SomeAssembly" publickey="d45755dbb8b44e59" />
</PackageHandler>
</PackageHandlers>
为什么要投否决票?阅读我链接到的博客文章,您将看到它确实显示了强命名如何链接到程序集签名,并且您可以使用它来验证程序集是否已使用特定证书进行签名。我正在通过API调用验证客户端计算机上的证书是否可信。如何在不将程序集加载到当前应用程序域的情况下检查公钥令牌?在.Net框架中似乎没有办法做到这一点。链接的博客文章当然很有帮助,但凭良心说,我不能投票给一个纯链接的答案。没有必要完全复制博客文章的内容,但至少这个答案应该包含对所用技术的提及(称为strongNameSignatureReferenceEx),如果未来的访问者因任何原因无法访问该链接,则允许他们独立研究该解决方案。@jmbpiano自2020年起高度相关,因为它似乎已经消失。这是Wayback机器为其编制索引的最后有效时间:
sn -tp <assembly>
<PackageHandlers>
<PackageHandler>
<Package type="Package1" assembyName="SomeAssembly" publickey="d45755dbb8b44e59" />
</PackageHandler>
</PackageHandlers>