用RAIL为没有强签名的程序集签名
你是否有过这样的经历,你的程序集需要强签名,但是你引用的一个第三方程序集没有强签名,那么你也因此不能为你自己的程序集强签名了。你并没有第三方程序集的源代码,所以你无法给它签名,但是你的安全策略要求你发布的程序集必须有强签名,怎么办呢?
这的确是个很棘手的问题,幸好有一个折中的方法。我们可以这样,将第三方程序集引用的程序集签名(方法同正在描述的一样),然后将要签名的这个第三方程序集反编译为IL,将这个IL编译成新的一个程序集并给予签名。这样,我们就得到了一个有签名的第三方程序集,我们在自己的项目中引用这个有强签名的程序集,这样一来,我们就可以强签名自己的程序集了!^_^
上面的是理论,实现起来可能比较复杂,现在我们可以借助RAIL来简单的达到这个目的。对于不了解RAIL的朋友,RAIL是.NET下一个非常好的Code Instrumentation Library,它的能力很强,简单地说就是能够将一个程序集的IL结构转成(parse)成对象,然后基于对象操作整个程序集的结构,比如删除一个类型,在一个方法中插入另一个方法的指令等等。
我们这里会活用RAIL,用RAIL加载一个程序集然后什么都不做就保存为另一个程序集,但是我们会在保存时加入强签名。值得一提的是,RAIL最新的版本0.5.7并没有对强签名做实现,而且在保存方面还有一些不足,以下是一些它的问题:
- 不能指定保存路径,自动保存到当前目录的上一级目录。不要问我为什么是上一级目录,我也不知道。
- 不能控制PDB文件的生成,自动生成,这个我个人觉得很烦。
- 没有实现强签名功能,保存后的程序集都是无强签名的。
- 在使用过程中发现了一个读取程序集结构的bug,读取构造函数时没有区分是.ctor还是.cctor(分别为实例构造函数与静态构造函数),导致调用错误,引起错误的IL输出。
针对以上问题,如果不解决掉的话就会使RAIL使用起来不够自然,不够自信,所以我动手了解了一番RAIL的源代码,终于把以上问题解决了。我用这个改动后的RAIL将RAIL自身引用的一个DLL强签名了(没有源码),然后又重新编译了一个有强签名的RAIL^_^ 这样一来RAIL就可以在有强签名的项目中被引用了。使用改动后的RAIL实现保存时签名的代码如下:
string asmFileName = Environment.CurrentDirectory + "\\DotSets.dll";
RAssemblyDef dotSets = RAssemblyDef.LoadAssembly(asmFileName);
// Save as a new assembly with strong name.
dotSets.SaveAssembly(Environment.CurrentDirectory + "\\saved\\DotSets.dll", false, @"E:\Work\Rail-Working\key.snk");
保存时的第一个参数为新程序集的路径,第二个参数为是否生成PDB文件,第三个参数为签名文件,如果指定为null的话就没有强签名。
我相信你一定也对RAIL感兴趣了吧,RAIL的能力很强,我准备用它实现一个AOP框架,目前还在需求挖掘阶段,有兴趣的并且代码规范执行的彻底的朋友可以联系我!:)
BTW,RAIL是葡萄牙的一所大学创建的,代码质量很差,不过技术能力很强。;)
在这里下载修改过的版本:https://files.cnblogs.com/cavingdeep/rail-modified-by-cavingdeep-v0.5.7.zip
License为Mozilla Public License 1.1