3.1 兩種程序集,兩種部署
CLR有兩種程序集,弱命名程序集和強命名程序集,二者基本一樣,區別:強命名程序集時用發布者的 公鑰/私鑰對 進行了簽名,唯一性的標識了程序集的發布者。弱命名程序集只能私有部署,強命名程序集 可以使用全局部署,也可以私有部署。
3.2 為程序集指派強名稱
一個強命名的程序集包括4部分重要屬性,標志唯一:一個無擴展名的程序集,一個版本號,一個語言 文化標志,一個公鑰publickey。此外,還使用發布者的私鑰進行簽名
MyTypes,Version=1.0.8123.0,Culture=neatral,PublicKeyToken=xxxxxxxxxxxxxxxx(公鑰標記)
MS使用公鑰/私鑰加密技術,這樣,沒有兩家公司有相同的公鑰/私鑰對(除非他們共享公鑰/私鑰對)。
使用反射獲取強命名程序集的PublicKeyToken
創建強命名程序集的步驟:
1.生成公鑰/私鑰對:使用SN命令,這個命令所有開關都區分大小寫
SN -k MyCompany.keys
——這裡MyCompany.keys是創建的文件名
2.將原有程序集升級為強命名程序集
csc /keyfile:MyCompany.keys app.cs
——這裡,app.cs是包含清單表的文件,不能對不包含清單表的文件簽名。C#編譯器會打開MyCompany ,使用私鑰對程序集進行簽名,並在清單中嵌入公鑰。
用私鑰簽名一個文件:是指生成一個強命名程序集時,程序集的FileDef清單中列出了包含的所有本件 ,將每個文件名稱添加到清單中,文件的內容都會根據私鑰進行哈希處理,得到的哈希值與文件名一起存 入FileDef中。這個哈希值稱為RSA數字簽名。
最終,生成的包含清單的PE32文件,其中會含有RSA數字簽名和公鑰
補充1:簽名默認使用SHA-1算法,也可以使用別的算法,通過AL命令的/algid開關指定。
補充2,還可以使用SN命令,在原有基礎上,得到只含公鑰的文件並顯示:
SN -p MyCompany.keys MyCompany.PublicKey
——這裡MyCompany.PublicKey是創建的公鑰文件名
SN -pt MyCompany.PublicKey
——顯示公鑰與公鑰標記
補充3:在IL中,Local對應於Culture
補充4:公鑰標記是公鑰的最後8個字節。
AssemblyRef中存的是公鑰標記,AssemblyDef存的是公鑰。
3.3 GAC 全局程序集緩存
GAC一般在C:\Windows\Assembly,結構化的,有很多子目錄。
使用Windows Explorer shell擴展來浏覽GAC目錄,這個工具是在安裝Framework時附帶的。
不能使用手動方法復制程序集文件到GAC,要使用GACUtil命令。
只能安裝強命名程序集到GAC中,而且要有Admin/PowerUser權限。
GAC的好處是可以容納一個程序集的多個版本。每個版本都有自己的目錄。缺點是違反了簡單安裝的原 則。
3.4 在生成的程序集中引用一個強命名程序集
第2章有講到,對於不完整路徑,csc編譯時目錄查找順序:
1.工作目錄(要編譯的cs文件所在)
2.系統目錄(csc.exe所在,同時也包括CLR DLL)
3./lib開關指定的目錄
4.LIB系統變量指定的目錄
安裝Framework時,會安裝.NET程序集兩套副本,一套在編譯器/CLR目錄——便於生成程序集,另一套 在GAC子目錄——便於在運行時加載它們。編譯時並不去GAC中查找。
3.5 強命名程序集能防范篡改
在安裝強命名程序集到GAC時,系統對包含清單的文件內容進行哈希處理,並將這個值與PE32文件中嵌 入的RSA數字簽名進行比較,如果一致,就再去比較其他文件內容(也是哈希處理在比RSA簽名)。一旦有一 個不一致,就不能安裝到GAC。
如果強命名程序集安裝在GAC以外的目錄,則會在加載時比較簽名。
3.6 延遲簽名(部分簽名) delayed signing
開發階段會使用到這個功能
允許開發人員只用公鑰來生成一個程序集,而不需要私鑰。
編譯時,會預留一定空間來存儲RSA數字簽名,不對文件內容進行哈希處理。CLR會跳過對哈希值的檢 查。以後可以再對其進行簽名。
步驟如下:
1.生成程序集:csc /keyfile: MyCompany.PublicKey /delaysign: MyAssembly.cs
2.跳過對哈希值的檢查: SN.exe -Vr MyAssembly.dll
3.准備私鑰,再次進行簽名: SN.exe -R MyAssembly.dll MyCompany.PrivateKey
4.再次延遲簽名: SN.exe -Vu MyAssembly.dll
3.7 私有部署強命名程序集
強命名程序集如果不在GAC中,每次加載都要進行驗證,有性能損失。
還可以設計為局部共享強命名程序集,指定配置文件的codeBase即可。
3.8 運行庫如何解析類型引用
在TypeRef中查找類型引用的紀錄,發現其強簽名,然後定位這個程序集的所在位置:會在以下三個地 方查找:
1.同一個文件:編譯時就能發現(早期綁定)
2.不同的文件,但同一個程序集:在FileRef表中
3.不同的文件,不同的程序集:這時要加載被引用的程序集,從中查找
注:AssemblyRef使用不帶擴展名的文件名來引用程序集。綁定程序集時,系統通過探測xx.dll和 xx.exe來定位文件。
ModuleDef,ModuleRef,FileDef使用文件名及其擴展名來引用文件。
注:在GAC中查找程序集時,除了名稱,版本,語言文化和公鑰,還需要CPU體系結構,而且是先根據 這個體系結構查找。