通過嵌入公鑰並使用私鑰簽名,可以生成強名稱(strong name)的程序集。強名稱程序集由4部分進行標識:名稱、版本、區域性和公鑰。與之相對的,我們可以把沒有嵌入公鑰和使用私鑰簽名的程序集稱之爲弱名稱(weak name)程序集(這個術語是Jffery Richter創造的)。強名稱程序集與弱名稱程序集相比,有以下特點:
- 強名稱程序集可以保證唯一性。公/私密鑰對是由發行者自行生成的,是唯一的,保證了程序集的標識不會重複。
- 強名稱程序集可以防篡改。強類型程序集使用私鑰對自己進行了簽名,這樣在被加載時可以檢查程序集是否被修改。
- 強名稱程序集可以實施版本策略。對於弱名稱程序集,引用它的程序不會關心它的版本,而對於強類型的程序集來說,引用它的程序會被綁定到特定版本的程序集上,如果使用新版本的強名稱程序集替換舊版本,會導致程序無法運行。(當然還可以使用配置文件對強名稱程序集進行重定向)。
- 強名稱程序集可以部署到GAC中。GAC指全局程序集緩存,這是一個公共目錄,放在此處的程序集可以被本機任意一個程序所引用。弱名稱程序集無法部署到此處。不同版本的相同程序集還可以同時存在於GAC中。
- 強名稱程序集只能引用強名稱程序集。弱名稱程序集可以引用強名稱程序集,也可以引用弱名稱程序集,但強名稱程序集只能引用強名稱程序集。
- 強名稱程序集支持並行執行。並行(side-by-side)執行是指程序同時引用了多個版本的同名程序集,這樣在運行時,會有多個版本的同名程序集被加載和同時執行。通常不建議使用。
下面來研究一下如何生成強名稱的程序集。首先,使用SN.exe創建一個密鑰文件:
sn.exe -k MyKey.snk
生成的文件包含了公鑰和私鑰的內容。我們可以查看公鑰的內容,私鑰是不允許查看的,所以要先將公鑰提取出來。仍然是使用SN.exe:
sn -p MyKey.snk MyPublicKey.snk
sn -tp MyPublicKey.snk
前一個命令將密鑰文件中的公鑰提取出來,放到 MyPublicKey.snk 文件中;後一個命令用於顯示該文件中的公鑰和公鑰標記(Public key token),顯示的內容可能如下(每個人生成的都不同):
Microsoft (R) .NET Framework Strong Name Utility Version 3.5.21022.8
Copyright (c) Microsoft Corporation. All rights reserved.
Public key is
0024000004800000940000000602000000240000525341310004000001000100757c8b7854ffcb
4763250746c094e45db0c715214415fb01bd178f3374224c1292dbbc9dddfb6af7de1766888464
1a39fbea9d0bee001c093b228400aa39c0db5724fc11c221bd2c7442a30ef26c076b1bb0f559ce
7955572b4174125494a593c199d968019323483e72d5bdb93d96af14ccfeb0c5d4af6ea191d226
e6812db5
Public key token is 337642649f453c2c
公鑰標記是公鑰的64位散列值,用於簡化對公鑰的引用。
第二步是創建強名稱程序集。我們可以在源文件中使用AssemblyKeyFileAttribute,但在編譯時會產生警告,建議使用命令行選項來代替此特性。所以此處使用csc.exe:
csc /t:library /keyfile:MyKey.snk MyType.cs
運行後得到 MyType.dll ,我們可以顯示其中包含的公鑰標記,看是否和上面的相同:
sn -Tp MyType.dll
顯示內容如下:
Microsoft (R) .NET Framework Strong Name Utility Version 3.5.21022.8
Copyright (c) Microsoft Corporation. All rights reserved.
Public key is
0024000004800000940000000602000000240000525341310004000001000100757c8b7854ffcb
4763250746c094e45db0c715214415fb01bd178f3374224c1292dbbc9dddfb6af7de1766888464
1a39fbea9d0bee001c093b228400aa39c0db5724fc11c221bd2c7442a30ef26c076b1bb0f559ce
7955572b4174125494a593c199d968019323483e72d5bdb93d96af14ccfeb0c5d4af6ea191d226
e6812db5
Public key token is 337642649f453c2c
由此可見,公鑰的內容確實嵌入到了程序集當中。除此之外,程序集的全部內容經過散列編碼後,還使用密鑰進行了簽名,也嵌入到了程序集中。
這樣我們就得到了一個強名稱程序集。如果有程序引用了該程序集,會記錄由以下內容標識的程序集:
MyType, Version=1.0.3087.28686, Culture=neutral, PublicKeyToken=337642649f453c2c
這些內容唯一的標識了一個強名稱程序集,由於公鑰太長,這裏只引用了公鑰標記。當程序運行時,CLR 會根據這些內容去搜尋程序集,只有完全匹配的程序集纔會被加載,即便是版本的細微差別都不會忽略。如果沒有找到,或者找到的程序集不匹配,都會產生異常。
參考文檔:
- MSDN
- Microsoft .NET Framework 程序設計
- C# 和 .NET 2.0 實戰:平臺、語言與框架
- .NET 本質論