DotNet强签名

一 如何使用强签名

Windows 软件开发工具包 (SDK) 提供了多种方法来使用强名称为程序集签名:

    *      使用 Windows SDK 提供的 程序集链接器 (Al.exe)。
    *      使用程序集属性将强名称信息插入代码中。您可以使用 AssemblyKeyFileAttribute 或 AssemblyKeyNameAttribute,这取决于要使用的密钥文件所在的位置。
    *      使用诸如 C# 和 Visual Basic 中的 /keyfile 或 /delaysign 编译器选项,或者 C++ 中的 /KEYFILE 或 /DELAYSIGN 链接器选项。

要使用强名称为程序集签名,必须具有加密密钥对。

    *   使用“程序集链接器”创建程序集并为其签署强名称
      在命令提示处,键入下列命令:
      al /out:<assembly name> <module name> /keyfile:<file name>
      在此命令中,assembly name 是要使用强名称签名的程序集的名称,module name 是用于创建程序集的代码模块的名称,file name 是包含密钥对的容器或文件的名称。
  下面的示例使用密钥文件 sgKey.snk 为程序集 MyAssembly.dll 签署强名称。
  al /out:MyAssembly.dll MyModule.netmodule /keyfile:sgKey.snk

    *   使用属性为程序集签署强名称
      在代码模块中,添加 AssemblyKeyFileAttribute 或 AssemblyKeyNameAttribute,指定在使用强名称为程序集签名时要用到的密钥对所在的文件或容器的名称。
  下面的代码示例使用具有名为 sgKey.snk 的密钥文件(位于编译程序集的目录中)的 AssemblyKeyFileAttribute。这假设该程序集是使用命令行编译器 vbc.exe 和 csc.exe 编译的。
  Visual Basic
  <Assembly:AssemblyKeyFileAttribute("sgKey.snk")>
  C#
  [assembly:AssemblyKeyFileAttribute(@"sgKey.snk")]

  *   使用 /keyfile为程序集签署强名称
  例如:csc.exe /debug+ /debug:full /optimize- /out:$(OUTDIR)\XXX.dll /target:library /keyfile:c:\ppk\XXXPrivateKey.snk .\*.cs

二 延迟为程序集签名
一个单位可以具有开发人员在日常使用中无法访问的严密保护的密钥对。公钥通常是可用的,但对私钥的访问权仅限于少数个人。开发强名称程序集时,每个引用具有强名称的目标程序集的程序集中都包含了用于为目标程序集指定强名称的公钥的标记。这要求公钥在开发过程中可用。
您可以在生成时使用延迟签名或部分签名,在可移植可执行 (PE) 文件中为强名称签名保留空间,但要将实际签名延迟至后面某些阶段(通常就在传送程序集之前)。

下面的步骤说明了延时对程序集签名的过程:
   1.      从将执行最终签名的单位获取密钥对的公钥部分。此密钥通常是 .snk 文件的形式,使用 Windows 软件开发工具包 (SDK) 提供的 强名称工具 (Sn.exe) 可创建此文件。
   2.      使用 System.Reflection 中的两种自定义属性来批注程序集的源代码:
          *            AssemblyKeyFileAttribute,它将包含公钥的文件的名称作为参数传递给其构造函数。
          *            AssemblyDelaySignAttribute,它通过将 true 作为参数传递给其构造函数,表明正在使用延迟签名。例如:
            Visual Basic
                <Assembly:AssemblyKeyFileAttribute("myKey.snk")>
                <Assembly:AssemblyDelaySignAttribute(true)>
            C#
                [assembly:AssemblyKeyFileAttribute("myKey.snk")]
                [assembly:AssemblyDelaySignAttribute(true)]
   3.      编译器将公钥插入程序集清单,并在 PE 文件中为完整的强名称签名保留空间。真正的公钥必须在生成程序集时存储,以便引用此程序集的其他程序集可获取密钥以存储在它们自已的程序集引用中。
   4.      由于程序集没有有效的强名称签名,所以必须关闭该签名的验证。您可以将“强名称”工具与 –Vr 选项一起使用来执行此操作。
      下面的示例关闭名为 myAssembly.dll 的程序集的验证。
      sn –Vr myAssembly.dll     
   5.      以后,通常是在即将交付前,将程序集提交给组织的签名机构,以便与“强名称”工具一起使用 –R 选项来实际进行强名称签名。
      下面的示例使用 sgKey.snk 密钥对为名为 myAssembly.dll 的程序集签署强名称。
      sn -R myAssembly.dll sgKey.snk


三 创建公匙密匙对
创建密钥对
    *      在命令提示处,键入下列命令:
      sn –k <file name>
      在此命令中,“文件名”是包含密钥对的输出文件的名称。
下面的示例创建名为 sgKey.snk 的密钥对。
sn -k sgKey.snk
如果您需要延迟对程序集签名并控制整个密钥对(密钥对不太可能在测试方案之外),可使用以下命令生成密钥对,然后从中将公钥提取到一个单独的文件中。首先,创建密钥对:
sn -k keypair.snk
    *      下一步,从密钥对中提取公钥,并将其复制到一个单独的文件中:
sn -p keypair.snk public.snk
    *      创建密钥对之后,必须将文件放在强名称签名工具可以找到的位置。
当使用强名称对程序集进行签名时, 程序集链接器 (Al.exe) 查找与当前目录和输出目录相关的密钥文件。当使用命令行编译器时,只需将密钥复制到包含代码模块的当前目录即可。

如果使用的是 Visual Studio 的早期版本,在项目属性中没有“签名”选项卡,则建议的密钥文件位置为按如下所示指定了文件属性的项目目录:
Visual Basic
<Assembly: AssemblyKeyFileAttribute("..\..\key.snk")>
C#
[assembly: AssemblyKeyFileAttribute(@"..\..\key.snk")]

四 引用具有强名称的程序集
引用强名称程序集中的类型或资源的过程通常是透明的。您可以在编译时(事先绑定)或在运行时进行引用。
当您向编译器表明程序集显式引用另一程序集时,发生编译时引用。使用编译时引用时,编译器会自动获取定为目标的强名称程序集的公钥,并将其放在正在编译的程序集的程序集引用中。
[说明] 说明:具有强名称的程序集只能使用其他具有强名称的程序集的类型。否则会危及具有强名称的程序集的安全。

对强名称程序集进行编译时引用
    *      在命令提示处,键入下列命令:
      <compiler command> /reference:<assembly name>
      在此命令中,compiler command 是您所用语言的编译器命令,assembly name 是引用的强名称程序集的名称。您也可以使用其他编译器选项(例如 /t:library 选项)创建库程序集。

下面的示例创建名为 myAssembly.dll 的程序集,该程序集从名为 myAssembly.cs 的代码模块中引用名为 myLibAssembly.dll 的强名称程序集。
csc /t:library myAssembly.cs /reference:myLibAssembly.dll

在运行时引用具有强名称的程序集
    *      若要在运行时通过使用 Assembly..::.Load 或 Assembly..::.GetType 之类的方法引用强名称程序集,必须使用引用的强名称程序集的显示名称。显示名称的语法如下:
<assembly name>, <version number>, <culture>, <public key token>
例如:
myDll, Version=1.1.0.0, Culture=en, PublicKeyToken=03689116d3a4ae33
在此示例中,PublicKeyToken 是公钥标记的十六进制形式。如果没有区域性值,请使用 Culture=neutral。

下面的代码示例说明如何以 Assembly.Load 方法使用该信息。
Visual Basic
Assembly.Load("myDll,Version=1.0.0.1,Culture=neutral,PublicKeyToken=9b35aa32c18d4fb1")
C#
Assembly.Load("myDll,Version=1.0.0.1,Culture=neutral,PublicKeyToken=9b35aa32c18d4fb1");

您可以使用下面的 强名称工具 (Sn.exe) 命令,为特定程序集输出十六进制格式的公钥和公钥标记:
sn -Tp <assembly>
如果您有公钥文件,则可改用以下命令(请注意命令行选项中大小写的区别):
sn -tp <assembly>

五 参考
创建和使用具有强名称的程序集:http://msdn.microsoft.com/zh-cn/library/xwb8f617.aspx
强名称工具 (Sn.exe):http://msdn.microsoft.com/zh-cn/library/k5b5tt23.aspx
posted @ 2009-09-11 17:33  iTech  阅读(3127)  评论(0编辑  收藏  举报