強(qiáng)名稱是由程序集的標(biāo)識(shí)加上公鑰和數(shù)字簽名組成的。其中,程序集的標(biāo)識(shí)包括簡單文本名稱、版本號(hào)和區(qū)域性信息(如果提供的話)。強(qiáng)名稱是使用相應(yīng)的 私鑰,通過程序集文件(包含程序集清單的文件,并因而也包含構(gòu)成該程序集的所有文件的名稱和散列)生成的。Microsoft? Visual Studio? .NET 和在 .NET Framework SDK 中提供的其他開發(fā)工具能夠?qū)?qiáng)名稱分配給一個(gè)程序集。強(qiáng)名稱相同的程序集應(yīng)該是相同的。
通過簽發(fā)具有強(qiáng)名稱的程序集,您可以確保名稱的全局唯一性。強(qiáng)名稱還特別滿足以下要求:
-
強(qiáng)名稱依賴于唯一的密鑰對(duì)來確保名稱的唯一性。任何人都不會(huì)生成與您生成的相同的程序集名稱,因?yàn)橛靡粋€(gè)私鑰生成的程序集的名稱與用其他私鑰生成的程序集的名稱不相同。
-
強(qiáng)名稱保護(hù)程序集的版本沿襲。強(qiáng)名稱可以確保沒有人能夠生成您的程序集的后續(xù)版本。用戶可以確信,他們所加載的程序集的版本出自創(chuàng)建該版本(應(yīng)用程序是用該版本生成的)的同一個(gè)發(fā)行者。
-
強(qiáng)名稱提供可靠的完整性檢查。通過 .NET Framework 安全檢查后,即可確信程序集的內(nèi)容在生成后未被更改過。但請(qǐng)注意,強(qiáng)名稱中或強(qiáng)名稱本身并不暗含信任級(jí)別,例如由數(shù)字簽名和支持證書提供的信任。
在引用具有強(qiáng)名稱的程序集時(shí),您應(yīng)該能夠從中受益,例如版本控制和命名保護(hù)。如果此具有強(qiáng)名稱的程序集以后引用了具有簡單名稱的程序集(后者沒有這 些好處),則您將失去使用具有強(qiáng)名稱的程序集所帶來的好處,并依舊會(huì)產(chǎn)生 DLL 沖突。因此,具有強(qiáng)名稱的程序集只能引用其他具有強(qiáng)名稱的程序集。
如果您需要在幾個(gè)應(yīng)用程序間共享程序集,可將其安裝到全局程序集緩存中。安裝了公共語言運(yùn)行庫的每臺(tái)計(jì)算機(jī)均具有此計(jì)算機(jī)范圍的代碼緩存。全局程序集緩存中存儲(chǔ)了專門指定給由計(jì)算機(jī)中若干應(yīng)用程序共享的程序集。要安裝到全局程序集緩存中,程序集必須具有強(qiáng)名稱。
|
全局程序集緩存中放置的程序集必須具有相同的程序集名稱和文件名(不包括文件擴(kuò)展名)。例如,程序集名稱為 myAssembly 的程序集必須具有名為 myAssembly.exe 或 myAssembly.dll 的文件。 |
應(yīng)當(dāng)只在必要時(shí)才將程序集安裝到全局程序集緩存中來共享程序集。一般原則是:程序集依賴項(xiàng)保持專用,并在應(yīng)用程序目錄中定位程序集,除非明確要求共享程序集。另外,您不必為了使 COM interop 或非托管代碼可以訪問程序集而將程序集安裝到全局程序集緩存。
要將程序集安裝到全局程序集緩存中的原因有以下幾點(diǎn):
-
共享位置。
可將應(yīng)用程序應(yīng)該使用的程序集放在全局程序集緩存中。例如,如果所有的應(yīng)用程序都應(yīng)使用位于全局程序集緩存中的程序集,則可將版本策略語句添加到 Machine.config 文件(此文件將引用重新定向到程序集)。
-
文件安全性。
管理員通常使用訪問控制列表 (ACL) 來保護(hù) systemroot 目錄,以控制寫入和執(zhí)行訪問。因?yàn)槿殖绦蚣彺姘惭b在 systemroot 目錄中,它繼承了該目錄的 ACL。建議只允許具有“管理員”權(quán)限的用戶從全局程序集緩存中刪除文件。
-
并行版本控制。
可在全局程序集緩存中維護(hù)程序集的多個(gè)副本(名稱相同但版本信息不同)。
-
其他搜索位置。
在探測(cè)或使用配置文件中的基本代碼信息之前,公共語言運(yùn)行庫會(huì)先檢查全局程序集緩存中符合程序集請(qǐng)求的程序集。
請(qǐng)注意,在有些情況下,您肯定不需要將程序集安裝到全局程序集緩存中。如果將組成應(yīng)用程序的某個(gè)程序集放在全局程序集緩存中,就無法再通過使用 XCOPY 復(fù)制應(yīng)用程序目錄來復(fù)制或安裝應(yīng)用程序。在這種情況下,還必須將程序集移到全局程序集緩存中。
全局程序集緩存
要使用 Visual Studio .NET 創(chuàng)建小型類庫項(xiàng)目、生成強(qiáng)名稱,以及在 GAC 中安裝項(xiàng)目的 .dll 文件,請(qǐng)按照下列步驟操作:
| 1. | 在 Visual Studio .NET 中,創(chuàng)建一個(gè)新 Visual C# .NET 類庫項(xiàng)目,并將該項(xiàng)目命名為 GACDemo 。 |
| 2. |
必須使用強(qiáng)名稱。要生成此加密密鑰對(duì),請(qǐng)使用 SN 工具。此工具位于安裝 .NET Framework 解決方案開發(fā)人員工具包 (SDK) 的 \bin 子目錄中。SN 工具易于使用。命令行語句采用以下形式:
sn -k "[DriveLetter]:\[DirectoryToPlaceKey]\[KeyName].snk"
|
| 3. |
在 C:\ 中創(chuàng)建一個(gè)名為
GACKey
的目錄,以便您可以輕松地找到密鑰,并從命令提示符處訪問該密鑰。
注意 : 對(duì)于大多數(shù)用戶,.NET 工具位于 C:\Program Files\Microsoft.NET\FrameworkSDK\Bin 中。鍵入以下 SN 命令前,可能需要在您的計(jì)算機(jī)上將與該路徑類似的路徑復(fù)制到 .NET bin 目錄中。從命令提示符處鍵入 cd ,右鍵單擊以粘貼該路徑,然后按 Enter,快速轉(zhuǎn)至 SN 工具所在的目錄。 鍵入以下內(nèi)容:
sn -k "C:\GACKey\GACkey.snk"
|
| 4. |
將生成一個(gè)密鑰,但是它與項(xiàng)目的程序集尚無關(guān)聯(lián)。要建立此關(guān)聯(lián),請(qǐng)?jiān)?Visual Studio .NET 解決方案資源管理器中雙擊 AssemblyInfo.cs 文件。此文件具有一個(gè)程序集屬性列表,默認(rèn)情況下,在 Visual Studio .NET 中創(chuàng)建項(xiàng)目時(shí)將包括這些屬性。在代碼中修改“AssemblyKeyFile”程序集屬性,如下所示:
[
assembly:AssemblyKeyFile("C:\\GACKey\\GACKey.snk")
]
通過按 Ctrl+Shift+B 來編譯項(xiàng)目。您不必具有任何附加代碼即可以在 GAC 中安裝 .dll 文件。
|
| 5. |
您可以通過使用 Gacutil 工具或者通過將 .dll 文件拖至適當(dāng)?shù)哪夸泚戆惭b .dll 文件。如果您使用 Gacutil 工具,則可以使用以下命令:
gacutil -I "[DriveLetter]:\[PathToBinDirectoryInVSProject]\gac.dll"
如果您要拖動(dòng)文件,請(qǐng)使用 Microsoft Windows 資源管理器。打開 Windows 資源管理器的兩個(gè)實(shí)例。在一個(gè)實(shí)例中,找到控制臺(tái)項(xiàng)目的 .dll 文件輸出的位置。在另一實(shí)例中,找到 c:\[SystemRoot]\Assembly。
將您的 .dll 文件拖到“Assembly”文件夾中。 |
用強(qiáng)名稱來給程序集簽名即謂之程序集強(qiáng)簽名!
那什么是強(qiáng)名稱,簽名又有什么作用?,我們先看看強(qiáng)名稱的概念是什么,強(qiáng)名稱是由程序集的標(biāo)識(shí)加上公鑰和數(shù)字簽名組成的,其中程序集的標(biāo)識(shí)包括簡單文本名稱,版本號(hào)和區(qū)域性信息!
Visual Studio.NET 和 .NET Framework SDK 中有工具能夠?qū)?qiáng)名稱分配給一個(gè)程序集!強(qiáng)名稱相同的程序集一般也是相同的!
好了,具體我們可以通過給程序集強(qiáng)簽名達(dá)到什么目的呢?
通過簽發(fā)具有強(qiáng)簽名的程序集合,可以確保名稱的全局唯一性!因?yàn)閺?qiáng)名稱是依賴于唯一的密鑰對(duì)來確保名稱的唯一性,其他人不會(huì)生成與你相同的程序集名稱(不同的私鑰產(chǎn)生的名稱不同)
強(qiáng)名稱保護(hù)程序集的版本沿襲,因?yàn)閺?qiáng)名稱的唯一性能夠確保沒有其他人能夠生成你的程序集的后續(xù)版本
強(qiáng)名稱提供可靠的完整性檢查,通過.NET Framework安全檢查后,可以確保程序集內(nèi)容在生成后未被更改過!
要注意的是,具有強(qiáng)名稱的程序集引用其他程序集,如果這個(gè)程序集沒有強(qiáng)名稱,那么具有強(qiáng)名稱的程序集所帶來的好處,并依舊會(huì)產(chǎn)生DLL沖突!因此具有強(qiáng)名稱的程序集只能引用其他具有強(qiáng)名稱的程序集。
強(qiáng)命名程序集(Strong Name Assembly)的概念
因?yàn)椴煌墓究赡軙?huì)開發(fā)出有相同名字的程序集來,如果這些程序集都被復(fù)制到同一 個(gè)相同的目錄下,最后一個(gè)安裝的程序集將會(huì)代替前面的程序集。這就是著名的Windows “DLL Hell”出現(xiàn)的原因。
很明顯,簡單的用文件名來區(qū)分程序集是不夠的,CLR需要支持某種機(jī)制來唯一的標(biāo)識(shí)一個(gè)程序集。這就是所謂的強(qiáng)命名程序集。
一個(gè)強(qiáng)命名程序集包含四個(gè)唯一標(biāo)志程序集的特性:文件名(沒有擴(kuò)展名),版本號(hào),語言文化信息(如果有的話),公有秘鑰。
這些信息存儲(chǔ)在程序集的清單(manifest)中。清單包含了程序集的元數(shù)據(jù),并嵌入在程序集的某個(gè)文件中。
下面的字符串標(biāo)識(shí)了四個(gè)不同的程序集文件:
“MyType, Version=1.0.1.0,
Culture=neutral, PublicKeyToken=bf5779af662fc055”
“MyType, Version=1.0.1.0,
Culture=en-us, PublicKeyToken=bf5779af662fc055”
“MyType, Version=1.0.2.0,
Culture=neturl, PublicKeyToken=bf5779af662fc055”
“MyType, Version=1.0.2.0,
Culture=neutral, PublicKeyToken=dbe4120289f9fd8a”
如果一個(gè)公司想唯一的標(biāo)識(shí)它的程序集,那么它必須首先獲取一個(gè)公鑰/私鑰對(duì),然后將共有秘鑰和程序集相關(guān)聯(lián)。不存在兩個(gè)兩個(gè)公司有同樣的公鑰/私鑰對(duì)的情況,正是這種區(qū)分使得我們可以創(chuàng)建有著相同名稱,版本和語言文化信息的程序集,而不引起任何沖突。
與強(qiáng)命名程序集對(duì)應(yīng)的就是所謂的弱命名程序集。(其實(shí)就是普通的沒有被強(qiáng)命名的程序集)。兩種程序集在結(jié)構(gòu)上是相同的。都使用相同的PE文件格 式,PE表頭,CLR表頭,元數(shù)據(jù),以及清單(manifest)。二者之間真正的區(qū)別在于:強(qiáng)命名程序集有一個(gè)發(fā)布者的公鑰/私鑰對(duì)簽名,其中的公鑰 /私鑰對(duì)唯一的標(biāo)識(shí)了程序集的發(fā)布者。利用公鑰/私鑰對(duì),我們可以對(duì)程序集進(jìn)行唯一性識(shí)別、實(shí)施安全策略和版本控制策略,這種唯一標(biāo)識(shí)程序集的能力使得應(yīng) 用程序在試圖綁定一個(gè)強(qiáng)命名程序集時(shí),CLR能夠?qū)嵤┠承耙汛_知安全”的策略(比如只信任某個(gè)公司的程序集)。
| How:實(shí)現(xiàn).NET Strong Named(強(qiáng)簽名)防止程序被篡改 |
|
對(duì).Net Assembly來說, 通過反射(Reflection)機(jī)制,得到一個(gè)Assembly里面所有的函數(shù)簽名是很簡單的.因此大家都可以制作一個(gè)和原Assembly具有完全一 樣接口的Assembly來讓系統(tǒng)或者應(yīng)用程序調(diào)用,這為dll hell提供了極大的便利。顯然,.Net需要提供一種機(jī)制來防止這樣的事情,尤其當(dāng)我們從網(wǎng)上更新Assembly的時(shí)候,我們?nèi)绾蜗嘈女?dāng)前得到 Assembly就是合法的那個(gè)呢? 一種辦法是讓Assembly的最初發(fā)布者提供簽名,程序只相信具有同樣簽名的Assembly,而且除了作者,別人不能生成這個(gè)簽名。.Net Runtime提供的就是這樣一個(gè)機(jī)制。 首先我們看一下.Net Runtime是怎么識(shí)別和導(dǎo)入一個(gè)DLL的。在.Net中當(dāng)我們說Assembly Name的時(shí)候,不是僅僅指其文件名(比如abc.dll)。實(shí)際 上,Assembly name是由四個(gè)部分構(gòu)成的:Friendly Name,Culture, Pubilc Key(Token), Version。除了Friendly Name 和 Version 是一定有的,其他兩個(gè)取決于開發(fā)者有沒有指定它們。比如像我這樣的初學(xué)者就不會(huì)去做一個(gè)有Public Key的程序,如果沒有指定的話,Culture=neutral,PublicKeyToken=null。本文忽略Culture和Version對(duì) 識(shí)別和導(dǎo)入一個(gè)DLL的影響,因?yàn)槟鞘橇硪黄恼隆N覀冎溃珹ssembly 導(dǎo)入有顯示導(dǎo)入和隱式導(dǎo)入兩種。顯示指的是使用Assembly.Load或者Assembly.LoadFrom來動(dòng)態(tài)導(dǎo)入一個(gè)Assembly到內(nèi)存 當(dāng)中。隱式指的是CLR自動(dòng)導(dǎo)入所要用到的Assembly(和我原先理解的不同的是,CLR并不是在在程序一開始運(yùn)行就導(dǎo)入所有Reference的 Assembly,而是當(dāng)一個(gè)數(shù)據(jù)類型被用到的時(shí)候,再去解析和導(dǎo)入對(duì)應(yīng)的Assembly)當(dāng)CLR Loader決定導(dǎo)入一個(gè)Assembly的時(shí)候,它一定會(huì)導(dǎo)入和Reference階段具有相同PublicKey或者PublicKeyToken的 Assembly。否則導(dǎo)入失敗。比如我們?cè)赗eference的abc Assembly的PublicKeyToken是1234123412341234,那么在運(yùn)行階段,它就會(huì)去找具有 1234123412341234PublicToken的Assembly,找不到便拋出異常。當(dāng)然如果Reference的Assembly不具備 Publickey,.Net Runtime 就會(huì)省略這個(gè)過程,由此,我們可以看出Pulic Key或者PublicKeyToken就是我們需要的數(shù)字簽名。我們將具有Public Key的程序稱之為強(qiáng)簽名程序。
那么到底什么是PublicKey和PublicKeyToken?
說了這么多理論,現(xiàn)在來看看具體怎么開發(fā)和部署具備Strong Name的Assembly吧,.Net SDK已經(jīng)為我們提供了一個(gè)非常好的工具Sn.exe. 下面就Step by Step吧,
1. 產(chǎn)生一個(gè)試驗(yàn)性的Assembly,隨便寫點(diǎn)代碼,用Visual Studio Class Library模板生成一個(gè)Assembly就叫 test.dll 吧. 代碼如下:
2.寫一個(gè)Console程序,Reference test.dll,調(diào)用A(),如下,
程序輸出:This is test App;
3.現(xiàn)在因?yàn)門est.dll不是Strong name的dll,任何人都可以冒用你的名義也生成一個(gè)test.dll,并且在#2的程序路徑下替換原來那個(gè),代碼如下:
9. 如果我是一個(gè)大項(xiàng)目的發(fā)布者,我不想讓團(tuán)隊(duì)的所有開發(fā)者都知道privatekey file,那么應(yīng)該使用 sn -p test.snk publickonly.snk, 生成一個(gè)只有Publick Key的文件,并讓團(tuán)隊(duì)開發(fā)者暫時(shí)使用Publickonly.snk來給程序簽名,并把test.snk藏起來,打死也不說。
|
強(qiáng)名稱工具 (Sn.exe) 來創(chuàng)建密鑰對(duì):
要使用強(qiáng)名稱為程序集簽名,必須具有公鑰/私鑰對(duì)。這一對(duì)加密公鑰和加密私鑰用于在編譯過程中創(chuàng)建強(qiáng)名稱程序集。您可以使用強(qiáng)名稱工具 (Sn.exe) 來創(chuàng)建密鑰對(duì)。密鑰對(duì)文件通常具有 .snk 擴(kuò)展名。
創(chuàng)建密鑰對(duì)
-
在命令提示處,鍵入下列命令:
sn –k <file name>
在此命令中,“文件名”是包含密鑰對(duì)的輸出文件的名稱。
下面的示例創(chuàng)建名為
sgKey.snk
的密鑰對(duì)。
sn -k sgKey.snk
|
如果您需要延遲對(duì)程序集簽名并控制整個(gè)密鑰對(duì)(密鑰對(duì)不太可能在測(cè)試方案之外),可使用以下命令生成密鑰對(duì),然后從中將公鑰提取到一個(gè)單獨(dú)的文件中。首先,創(chuàng)建密鑰對(duì):
sn -k keypair.snk
|
-
下一步,從密鑰對(duì)中提取公鑰,并將其復(fù)制到一個(gè)單獨(dú)的文件中:
sn -p keypair.snk public.snk
|
-
創(chuàng)建密鑰對(duì)之后,必須將文件放在強(qiáng)名稱簽名工具可以找到的位置。
當(dāng)使用強(qiáng)名稱對(duì)程序集進(jìn)行簽名時(shí),程序集鏈接器 (Al.exe) 查找與當(dāng)前目錄和輸出目錄相關(guān)的密鑰文件。當(dāng)使用命令行編譯器時(shí),只需將密鑰復(fù)制到包含代碼模塊的當(dāng)前目錄即可。
如果要使用 IDE(例如 Visual Studio 2005)為程序集簽署強(qiáng)名稱,則必須知道 IDE 查找密鑰文件的位置。例如, C# 編譯器則在包含二進(jìn)制文件的目錄下查找密鑰文件。將密鑰文件放在適當(dāng)?shù)捻?xiàng)目目錄中并設(shè)置文件屬性,如下所示:
|
C#
|
[assembly: AssemblyKeyFileAttribute(@"..\..\key.snk")]
|
NET程序集強(qiáng)簽名收藏 強(qiáng)名稱工具 (Sn.exe) 來創(chuàng)建密鑰對(duì):
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

