認識程序集:2. 生成強名稱程序集

通過嵌入公鑰並使用私鑰簽名,可以生成強名稱(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 本質論
發佈了3 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章