强命名程序集能防篡改工具
用私钥对程序集进行签名,并将公钥和签名嵌入程序集,CLR就能够炎症程序集未被修改或破坏。程序集安装到GAC时,系统对包含清单的那个文件的内容进行哈希处理,将Hash值与PE文件中嵌入的RSA数字签名进行比较。若是两个值彻底一致,代表内容未被篡改。此外,系统还对程序集的其余文件的内容进行哈希处理,并将Hash值与清单文件的FileDef中存储的哈希值进行比较。任何一个哈希值不匹配,代表程序集至少有一个文件被篡改,程序集将没法安装到GAC。性能
应用程序须要绑定到程序集时,CLR根据被引用的程序集的属性在GAC中找到该程序集。找到被引用的程序集,就返回包含他的子目录,并加载清单所在的文件。以这种方式查找程序集,可保证运行时加载的程序集和最初编译时生成的程序集来自同一个发布者,由于进行引用的程序集的AssemblyRef表中的公钥标记与被引用程序集的AssemblyRef表中的公钥匹配。若是被引用程序集不在GAC中,CLR会查找应用程序的基目录,而后查找应用程序配置文件中标注的任何private路径。而后,若是应用程序由MSI安装,CLR要求MSI定位程序集。若是在任何位置都找不到程序集,那么绑定失败,抛出异常。测试
若是强命名程序集文件从GAC以外的位置加载,CLR会在程序集加载后比较哈希值。也就是说,每次应用程序执行并加载程序集时,都会对文件进行hash处理,以牺牲性能为代价,保证程序集文件内容没有被篡改。CLR在运行时检测到不匹配的哈希值会抛出异常。spa
注:将强命名程序集安装到GAC时,系统会执行检查,确保包含清单的文件没有被篡改。这个检查仅在安装的时候执行一次。除此以外,为了加强性能,若是强命名程序集被彻底信任,并加载到彻底信任的APPDomain中,CLR将不检查该程序集是否被篡改。相反,从那个飞GAC的沐浴露加载强命名程序集时,CLR会校验程序集的清单文件,确保文件内容未被篡改,形成该文件每次加载都形成额外的性能开销。命令行
延迟签名开发
SN.exe工具生成公钥/私钥对时,会调用Windows提供的Crypto API。密钥可存储到文件或其余存储设备中。例如,大公司会将本身的私钥保存到一个硬件设备中,再将硬件锁进保险库。公司只有少数人才能访问私钥。这项措施能够防止私钥泄露,并保证了密钥的完整性。固然,公钥是彻底公开的,能够自由分发。部署
准备打包本身的强命名程序集时,必须使用受严密保护的私钥对它进行签名。然而,在开发和测试程序集时,访问这项受严密保护的私钥可能有点碍事。所以,.Net提供了延迟签名,该技术也被称为部分签名。延迟签名容许只用公司的公钥生成程序集,暂时不用私钥。因为使用了公钥,引用了程序集的其余程序集会在他们的AssemblyRef元数据表的记录项中嵌入正确的公钥值。另外,它还使程序集能正确存储到GAC的内部结构中。固然,不用公司的私钥对文件进行签名,便没法实现防篡改保护。这是由于没法对程序集的文件进行哈希处理,没法在文件中嵌入数字签名。然而,失去这种保护不是一个大问题,由于只是在开发阶段才延迟签名。打包和部署程序集确定会签名。编译器
为了实现延迟签名,须要获取存储在文件中的公钥值,将文件名传给用于生成程序集的实用程序。另外,还必须让工具知道你想延迟对程序集的签名,暂不提供私钥。hash
编译器或AL.exe一旦检测到要对程序集进行延迟签名,就会生成程序集的AssemblyDef清单记录项,其中将包含程序集的公钥。公钥使程序集能正确存储到GAC。另外,这也不妨碍引用了改程序集的其余程序集的正确生成。在进行引用的程序集的AssemblyRef元数据表记录项中,会包含正确公钥。建立程序集时,会在生成的PE文件中为RSA数字签名预留空间。文件内容不会在这个时候进行哈希处理。编译
目前生成的程序集没有有效签名。安装到GAC会失败,由于还没有对文件内容执行哈希处理——文件表面上已被篡改了。在须要安装到GAC的每台机器上,都必须禁止系统验证程序集文件的完整性。这要求使用SN.exe实用程序并指定-Vr命令行开关。用这个开关执行SN.exe,程序集的任何文件在运行时加载时,CLR都会跳过对其哈希值的检查。
结束程序集的开发和测试以后,就要正式对其签名,以便打包和部署。为了对程序集进行签名,要再次使用SN.exe实用程序,使用-R开关,并指定了包含私钥文件的名称。-R开关指示SN.exe对文件内容进行哈希处理,用私钥对其进行签名,并将RSA数字签名嵌入文件中以前的预留空间。这样,就能够部署彻底签好名的程序集。