如何使用强程序集名称和密钥文件来验证我正在加载的 DLL 是否符合我的预期?

发布于 2024-07-28 03:33:42 字数 497 浏览 4 评论 0原文

我有一个项目需要以编程方式加载 DLL 并在其中运行一些代码。 DLL 及其依赖项存储在数据库中,我将它们写入磁盘,但我想在再次写入之前检查 DLL 是否已经存在。 目前,数据库包含文件的强程序集名称和二进制数据以及版本号。 我想我还需要存储程序集的公钥,以检查 DLL 目录中现有文件的密钥。

我知道我可以使用 AssemblyName.GetPublicKey() 获取程序集的公钥。 我是否应该将文件的公钥也存储在数据库中? 如果代码中没有公钥(可以吗),如何验证程序集? 我发现的所有代码示例实际上只是显示获取公钥或检查强名称是否存在。

现在,我正在开发一个图书馆管理类,其核心只是一个字典。 它在启动时检查 dll 目录并将每个文件的公钥添加到字典中。 然后,当我需要检查程序集是否已在磁盘上时,我可以只检查字典(但这需要我将公钥存储在数据库中)。 它还使用 FileSystemWatcher 来监视对库的任何更改。 如果我需要编写更新的程序集,我只需覆盖磁盘上的程序集,类就会更新字典。

I've got a project going where I need to programmatically load DLLs and run some code in them. The DLLs and their dependencies are stored in a database, and I write them to disk, but I want to check if a DLL is already there before writing it again. Currently, the database contains the strong assembly name and binary data of the file and a version number. I'm thinking I also need to store the public key for the assembly to check against the key of the existing files in the DLL directory.

I know I can get the public key of the assemblies using AssemblyName.GetPublicKey(). Should I just store the public key of the file in the database also? How is an assembly verified if you don't have the public key in your code (can it be)? All the code examples I have found really just show getting the public key or checking that a strong name exists.

Right now, I'm working on a library management class that is just a Dictionary at it core. It checks the dll directory on start up and adds the public key of each file to the dictionary. Then, when I need to check if an assembly is already on disk, I can just check the dictionary (but this requires me storing the public key in the database). It also uses FileSystemWatcher to monitor any changes to the libraries. If I need to write an updated assembly, I just overwrite the one on disk and the class updates the dictionary.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

书信已泛黄 2024-08-04 03:35:51

我发现我不能依赖 DotNET 框架来真正加载我要求的程序集。 它有时会返回另一个具有更高版本号的程序集(这太聪明了)。

现在,我将程序集文件读入内存,然后从 COFF 流加载程序集:

''' <summary>
''' Converts a DotNET class library to a COFF-based image containing the entire assembly
''' </summary>
Public Shared Function ReadAssembly(ByVal iPath As String) As Byte()
  If (Not IO.File.Exists(iPath)) Then Return Nothing

  Try
    Dim file_info As New FileInfo(iPath)
    Dim file_byte(Convert.ToInt32(file_info.Length)) As Byte
    Dim file_stream As New FileStream(iPath, FileMode.Open)

    file_stream.Read(file_byte, 0, file_byte.Length)
    file_stream.Close()

    Return file_byte

  Catch ex As Exception
    Kernel.EH_LogServer.AddMessage("Assembly reading failed: " & ex.Message, EH_RuntimeMessageType.Error)
    Return Nothing
  End Try
End Function

然后调用 Assembly.Load(coff_image)

我将对字节数组运行 CRC 检查,以查看两者之间是否存在差异组件。

I found that I cannot rely on the DotNET framework to really load the assembly I'm asking for. It sometimes returns another assembly which has a higher version number (it's too clever).

Now I read the assembly file into memory, then load the assembly from the COFF stream:

''' <summary>
''' Converts a DotNET class library to a COFF-based image containing the entire assembly
''' </summary>
Public Shared Function ReadAssembly(ByVal iPath As String) As Byte()
  If (Not IO.File.Exists(iPath)) Then Return Nothing

  Try
    Dim file_info As New FileInfo(iPath)
    Dim file_byte(Convert.ToInt32(file_info.Length)) As Byte
    Dim file_stream As New FileStream(iPath, FileMode.Open)

    file_stream.Read(file_byte, 0, file_byte.Length)
    file_stream.Close()

    Return file_byte

  Catch ex As Exception
    Kernel.EH_LogServer.AddMessage("Assembly reading failed: " & ex.Message, EH_RuntimeMessageType.Error)
    Return Nothing
  End Try
End Function

Then it's a matter of calling Assembly.Load(coff_image)

I'd run a CRC check on the byte-array to see if there's a difference between two assemblies.

赏烟花じ飞满天 2024-08-04 03:35:12

我想你可以重用 SN 数据,但我不会。 首先,仅仅获得公钥是不够的,公钥不会随着版本的不同而改变。 相反,您需要提取使用私钥加密的哈希值。 我暂时不知道该怎么做,所以这是我尝试其他方法的原因之一。

相反,我会确保每个版本的版本号是唯一的,然后使用它。 如果您确实必须这样做,您可以使用 SHA1 类来运行您自己的哈希,但这似乎有些偏执。

编辑

需要明确的是,公钥用于解密存储的哈希值,然后将其与新生成的哈希值进行比较。 任何公钥都可以工作,这就是为什么加载程序必须使用强名称,它指定允许的公钥。

此外,您应该存储完整的强名称,而不仅仅是公钥。 这包括版本和公钥。

I suppose you could reuse the SN data, but I wouldn't. First, it's not enough to get the public key, which isn't going to change from version to version. Rather, you would need to extract the hash that's encrypted with the private key. I don't offhand know how to do that, so that's one reason I'd try something else.

Instead, I would ensure that the version number of each build was unique and just use that. If you really must, you could use the SHA1 class to run your own hash, but that seems paranoid.

edit

Just to be clear, the public key is used to decrypt the stored hash, which is then compared against a freshly generated hash. Any public key will work, which is why the loading program has to use the strong name, which specifies the allowed public key.

Also, you should be storing the full strong name, not just the public key. This includes the version and the public key.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文