学习.NET (4) Inside Assembly -研究Assembly的结构,强命名Assembly的生成以及Delayed signing的过程

Inside assembly

-研究Assembly的结构,强命名Assembly的生成以及Delayed signing的过程

By Alva Chien

 

File Version: 1.0

Released: 2007.6.4

 

.NET平台的Module文件

一个.NET上的Module(模块)文件由4个部分组成:

1. PE32+ Header: 标准的Windows平台上的PE格式信息,通常包括文件的类型 (GUI/CUI/DLL),CPU平台(anycpu/x86/x64/IA64) 等。这里的信息可以被Windows Explorer查看。

2. CLR Header:这个Header包含了该Assembly被创建时的.NET Framework版本 (也就是该Assembly可以被运行的最低版本) Metadata的大小和起始位置,resources,入口地址 (如果是EXE格式) Strong name(强命名)所必须的数据。

3. Metadata:由二进制数字构成的一堆表。共有三种类型的表:Definition(定义),Reference(引用),以及Manifest表。

4. IL:该module中所包含的IL代码。

 

Module文件的Metadata中的DefinitionReference表使得一个Module可以自描述。属于Definition表有ModuleDef, TypeDef, MethodDef, FieldDef, ParamDef, PropertyDef, EventDef等,而Reference表则有AssemblyRef, TypeRef, MemberRef等。这完全避免了DLLLib库,COM中的IDLManifest表有AssemblyDefFileDefManifestResourceDef以及ExportedTypesDef等表。

 

Assembly的概念

Assembly.NET平台进行重用的单元,它完全是一个抽象的概念,类似于程序。通常说一个程序,可以是一个单一的EXE文件,但是更多的时候是指一大堆文件的组合,比如微软的Word,不是指一个WinWord.exe,而是指以WinWord.exe为入口的一系列文件的集合,因为仅仅一个WinWord.exe是无法正常运行的。Assembly也一样,它同样是一个或多个Module文件或者资源(也可能是数据)文件的组合。一个Assembly必须有一个 (且只有一个) module文件(本文中称之为主Module)中的Metadata中包含Manifest表,这个主module文件就是Assembly的入口。CLR装载Assembly时就装载该module,而该Assembly的其它module则只是在需要访问时才会装载。

 

.NET中,Assembly只能是一个EXE或者是DLL文件,同时Assembly是拥有Security信息和版本信息的实体,这些信息被存储于拥有Manifest表的Module中。

 

Strongly named assembly(强命名Assembly

一个Strongly named assembly拥有4个要素:名称,版本信息,Culture以及Public key,也正是这4个要素使得它们彼此唯一。其中,Public key是一个非常大的数字,所以通常使用的是Public key token,这个值是对Public key进行hash运算后取最后8Byte(共64位)。

 

事实上,当一个Assembly引用别的Assembly,所有的上述4个要素都被存储于该AssemblyMetadataAssemblyRef表中了。比如,基本上每个Assembly都要引用的mscorlib的信息(ILDaasm的显示结果)

AssemblyRef #1 (23000001)

Token: 0x23000001

Public Key or Token: b7 7a 5c 56 19 34 e0 89

Name: mscorlib

Version: 2.0.0.0

Major Version: 0x00000002

Minor Version: 0x00000000

Build Number: 0x00000000

Revision Number: 0x00000000

Locale: <null>

HashValue Blob:

Flags: [none] (00000000)

这些信息描述了这样的一个Assembly:“MSCorLib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”。当然,只所以只存储Public key token,因为Public key实在太过巨大。根据这些信息,CLR在运行时会准确得从GAC中找到对应的Assembly

 

创建一个Strongly named assembly

创建一个Strongly named assembly时对主Module所做的修改:

1. Manifest部分
   FileDef表:重建整个FileDef表,跟非Strongly name assembly不同的是,不仅仅将Assembly中除主Module之外的Module文件或者资源数据文件的名称加入该表,而且将这些文件的hash value同样存放于该表,生成该hash值的算法可以由用户自定义(通过使用AL.exe/algid或者在代码中指定AssemblySystem.Reflection.AssemblyAlgorithmIdAttribute属性),默认情况下使用SHA-1算法。
AssemblyDef表,将嵌入该Assembly完整的Public Key(注意这里不是Public key token)。

2. CLR Header部分
   当包含了Strong name assemblyManifest信息被完整创建之后,整个PE文件(这里指的是主Module文件,该运算不包含Authenticode Signature用户签名部分,该AssemblyStrongly name数据以及PE Header中的checksum)将被运算hash值,使用的hash算法是SHA-1(无法更改),然后将得到的hash value使用发布者的private key签名(RAS数字签名算法),并将最终结果存储在CLR header的预保留空间中。其它三个构成Strong name assembly的要素:名称,Culture以及版本同样被存储在CLR Header中。

 

CLRStrongly Named Assemblies的保护机制

1.     安装到GAC
当安装一个Strongly named assembly时,系统会重新对Assembly的主module文件进行Hash值运算,该运算过程跟创建CLR Header中的RAS签名数值完全一致,并将运算的RAS签名结果跟存储在CLR Header的结果进行比较,如果两个值不同,则安装失败。接着,系统会对该Assembly中其它文件取Hash值,整个过程也完全类似于创建FileDefHash值的过程,同样,系统会逐一比较文件的Hash值,如果出现值不同,则安装失败。

2.     运行时的查找和装载
当需要从GAC装载一个特定的Assembly时,系统根据AssemblyRef信息来定位该Assembly,如果GAC中存在该Assembly,则不会再进行校验,而直接将该Assembly返回。如果查找不成功,会在程序所在目录以及程序配置文件指定的probe路径查找,当找到该Assembly并发现该AssemblyStrongly named assembly时,系统会再次进行一系列的hash值的运算(跟安装到GAC完全相同)以及比较来确保该Assembly没被破坏。所以,把使用到的Strongly name assembly安装到GAC会提高程序性能。

 

Delayed signing

所谓的Delayed signing就是在没有private key(也就是只有public key)的情况下给文件签名的一种机制,它只针对strongly named assembly。根据上文的描述,没有private key,就没法对主module文件生成的hash值进行RAS数字签名,所以Assembly的主module文件的CLR Header也就没有该部分信息(该部分大小还是被预留)。同样,因为该部分RAS签名内容的缺少,所有CLR对文件的保护都将失效。注意,别的Assembly无法分辨该assembly是否是完整的strongly named assembly,因为该AssemblyAssemblyDef表中的Public key 同样被嵌入,还有FileDef表中的Hash值也一样被运算后嵌入。

 

创建一个Delayed signingstrongly named assembly,需要编译器的特殊编译开关。对C#编译器(CSC.exe)而言,该编译开关为/delaysign;对AL.exe而言,则为/delay[sign]。同样,安装一个Delayed signingassemblyGAC也需要特殊的指令,使用SN.exe-Vr命令行参数来指定需要忽略hash值校验的Assembly(该操作其实就是在注册表的HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/StrongName/Verification路径下增加该Assembly的信息)。当需要对该Assembly进行正确签名时(通常这个任务由掌握了private key的人实施),使用SN.exe-R命令行参数并同时指定Assembly的名称以及private key文件(该操作将真正的向对应的Assembly嵌入CLR HeaderRAS签名,当然该RAS签名是由private key对文件的hash值运算而来)。最后,要取消CLR对该AssemblyGAC的忽略检查机制,通过运行SN.exe-Vu-Vx参数(该操作其实就是到注册表中删除对应的AssemblyKey)。

 

其它

常用的几个任务:

使用SN.exe来创建public/private密钥对: sn -k mykeys.keys

从密钥对文件中得出public key文件:sn -p mykeys.key mypublickey.publickey

显示public key文件中的内容: sn -tp mypublickey.publickey

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值