当前位置:首页 > C# > 正文

C#动态程序集的签名与验证(小白也能掌握的强名称签名实战教程)

在 .NET 开发中,C#动态程序集 是指在运行时通过代码生成并加载的程序集。这类程序集常用于插件系统、AOP 编程、ORM 映射等高级场景。然而,为了确保程序集的来源可信、防止篡改,我们需要对其进行程序集签名,尤其是使用 强名称签名(Strong Name Signing)。本教程将手把手教你如何为动态生成的程序集添加签名,并进行验证。

C#动态程序集的签名与验证(小白也能掌握的强名称签名实战教程) C#动态程序集 程序集签名 强名称签名 C#反射 第1张

什么是强名称签名?

强名称签名是 .NET 提供的一种机制,它使用公钥/私钥对来唯一标识一个程序集。签名后的程序集具有以下特性:

  • 唯一性:避免命名冲突
  • 完整性:防止程序集被篡改
  • 信任链:可被其他强名称程序集引用

动态程序集能否签名?

很多人误以为只有编译后的 .dll 才能签名。实际上,通过 System.Reflection.Emit 命名空间,我们可以在运行时创建动态程序集,并为其指定强名称密钥对。但需要注意:动态程序集默认保存在内存中,无法直接写入磁盘进行传统签名,因此必须在创建时就提供密钥信息。

步骤一:生成强名称密钥对

首先,使用 .NET SDK 自带的 sn.exe 工具生成密钥对:

sn -k MyKey.snk  

这将生成一个名为 MyKey.snk 的文件,包含公钥和私钥。

步骤二:在 C# 中加载密钥并创建签名的动态程序集

下面是一个完整的示例,展示如何使用 AssemblyBuilder 创建一个带有强名称签名的动态程序集:

using System;using System.IO;using System.Reflection;using System.Reflection.Emit;// 读取 .snk 文件byte[] keyPair = File.ReadAllBytes("MyKey.snk");// 定义程序集名称并指定公钥AssemblyName assemblyName = new AssemblyName("DynamicSignedAssembly"){    KeyPair = new StrongNameKeyPair(keyPair)};// 创建动态程序集(可执行)AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(    assemblyName,    AssemblyBuilderAccess.RunAndSave // 必须支持保存才能签名);// 定义模块ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(    "MainModule",     "DynamicSignedAssembly.dll");// 定义一个简单类型TypeBuilder typeBuilder = moduleBuilder.DefineType(    "HelloWorld",    TypeAttributes.Public);// 添加一个方法MethodBuilder methodBuilder = typeBuilder.DefineMethod(    "SayHello",    MethodAttributes.Public | MethodAttributes.Static,    typeof(void),    Type.EmptyTypes);// 生成方法体ILGenerator il = methodBuilder.GetILGenerator();il.Emit(OpCodes.Ldstr, "Hello from signed dynamic assembly!");il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));il.Emit(OpCodes.Ret);// 创建类型typeBuilder.CreateType();// 保存程序集到磁盘(此时会自动应用强名称签名)assemblyBuilder.Save("DynamicSignedAssembly.dll");Console.WriteLine("动态程序集已生成并签名!");  

步骤三:验证程序集是否已签名

可以使用 sn.exe 工具验证生成的程序集是否具有有效签名:

sn -v DynamicSignedAssembly.dll  

如果输出 “Assembly ‘DynamicSignedAssembly.dll’ is valid”,说明签名成功。

注意事项与常见问题

  • 必须使用 RunAndSave 模式:只有支持保存的动态程序集才能应用强名称签名。
  • 密钥文件路径要正确:确保 MyKey.snk 在运行目录或指定绝对路径。
  • 仅限 .NET Framework:在 .NET Core / .NET 5+ 中,强名称签名的行为有所变化,部分 API 已弃用。建议在 .NET Framework 环境下实践本教程。
  • 安全性提示:私钥(.snk)应妥善保管,切勿泄露。

结语

通过本教程,你已经掌握了如何为 C#动态程序集 添加 强名称签名,并验证其完整性。这项技术在构建安全、可信的插件系统或代码生成框架时非常有用。记住,签名不仅是技术需求,更是安全实践的重要一环。

关键词回顾:C#动态程序集程序集签名强名称签名C#反射