0

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

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

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

4

2 回答 2

0

我发现我不能依赖 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 检查,以查看两个程序集之间是否存在差异。

于 2009-07-24T15:25:00.973 回答
0

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

相反,我会确保每个构建的版本号都是唯一的,并且只使用它。如果你真的必须,你可以使用 SHA1 类来运行你自己的哈希,但这似乎是偏执的。

编辑

需要说明的是,公钥用于解密存储的散列,然后将其与新生成的散列进行比较。任何公钥都可以使用,这就是加载程序必须使用强名称的原因,它指定了允许的公钥。

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

于 2009-07-24T15:33:33.127 回答