解説

インサイド .NET Framework [改訂版]

第2回 アセンブリのアイデンティティ

吉松 史彰
2003/07/02

Page1 Page2 Page3 Page4 Page5

アセンブリへの参照

 アセンブリの名前(アイデンティティ)についてはもう1つ触れておかなければならない点がある。それは、ほかのアセンブリへの参照だ。

 前ページで作成したuser.exeのマニフェストをildasm.exeで確認した内容をもう1度見てみよう。

.assembly extern util
{
  .publickeytoken = (BA 69 B5 76 33 AC EE E8 )           // .i.v3...
  .ver 1:0:0:0
}
サンプル・プログラムuser.exeのマニフェスト(再掲)

 一方、util.dllに入っている、utilアセンブリのマニフェストもildasm.exeで見てみると、次のような内容になっている(抜粋)。

.assembly util
{
  .publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00   // .$..............
                00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00   // .$..RSA1........
                A1 23 25 7C AC EA 68 C1 F2 D6 EF 7E 9C 99 68 A5   // .#%|..h....~..h.
                30 A6 80 EA AA E4 1D 6F C9 33 E7 2C CB 79 8C E0   // 0......o.3.,.y..
                ED 7B 1D A0 3B 82 6F E8 69 B9 4A 99 67 3D F7 F9   // .{..;.o.i.J.g=..
                7E 4A A5 04 A6 67 07 2B 10 2E A5 10 49 86 A2 1A   // ~J...g.+....I...
                84 F0 D3 C4 C9 F7 2B 44 A0 2E 57 D5 64 F4 70 47   // ......+D..W.d.pG
                95 88 AB B5 81 D3 9B 91 99 F3 C6 CB 0A 59 DB 8C   // .............Y..
                4C B9 7B A8 20 B1 A0 27 7A 36 7E 0D 42 DA 6F 90   // L.{. ..'z6~.B.o.
                01 F9 D2 0A 17 A3 D2 53 E9 2C 0C 56 DF 47 4A A7 ) // .......S.,.V.GJ.
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
サンプル・プログラムutil.dllに入っているutilアセンブリのマニフェスト

 何がいいたいかというと、utilアセンブリ本人のマニフェストには“.publickey=”の中に公開キーが書いてあるが、それを参照しているuser.exeのアセンブリの方には“.publickeytoken=”という指定で、はるかに少ない情報しか書いていないということだ。名前のとおり、.publickeyに書いてあるのは、このアセンブリに署名したときに使った秘密キーに対応する公開キーだ。それでは“.publickeytoken”とはいったい何だろうか。

 コンポーネント指向の.NET Frameworkでは、あるアセンブリはほかのたくさんのアセンブリを参照する。アセンブリを参照するときには、アセンブリの名前を使う。.NET Frameworkでは、自分が利用するアセンブリに関する情報はすべてマニフェストや各モジュールのメタデータに書いてある(これを自己記述的という)ので、実行にあたって必要なファイルはほかの場所(レジストリやiniファイルなど)を見なくても分かるようになっている。

 だが、これは問題も引き起こす。参照しているアセンブリが増えると、ファイル・サイズが増大してしまうのだ。公開キーはかなりのサイズ(128byte=1024bit)になるので、これが含まれるアセンブリの名前を参照しなければならないとしたら、参照しているアセンブリが1つ増えるたびに128byteずつサイズが増えてしまうことになる。これでは困る。

 そこでCLRは、参照するアセンブリの名前の一部として利用するときは、通常は公開キー全体ではなく、公開キーにハッシュをかけて抽出した値の最後の8byteを公開キー・トークンとして利用する。上記のutilアセンブリを参照しているuser.exeの内容はこの公開キー・トークンである。公開キー・トークンは公開キーではない。つまり、アセンブリのマニフェストには、

  1. 自分を表す、自分を署名した秘密キーと対になる公開キー(全体)
  2. ほかのアセンブリを表す、そのアセンブリを署名した秘密キーと対になる公開キーから生成された公開キー・トークン

の2つが入っているということだ。アセンブリの参照に公開キー全体を利用することは不可能ではないが、ほとんどないといっていいだろう。

アセンブリ参照の作成 

 冒頭で説明したとおり、アセンブリの名前は4つの部分からなるデータ構造になっている。モジュールがほかのアセンブリを参照していると、参照しているアセンブリの名前(簡易名ではない)がそのモジュールのメタデータに含まれている。つまり、上記4つの情報を含む構造がモジュールのメタデータに格納されているということだ。この情報は通常はコンパイラが生成してモジュールに格納する。例えばC#やVB.NETのコンパイラは、“/reference”というスイッチで指定されたファイル(アセンブリのメイン・モジュール)からマニフェストを取り出して、中に書いてあるそのアセンブリの名前を取り出し、今コンパイルしているモジュールのメタデータに参照先として出力する。このとき出力される名前は、簡易名、バージョン、カルチャと、公開キーではなく公開キー・トークンからなる名前なのである。

アセンブリの表示名

 今回の最後に、アセンブリの名前の一般的な表示方法を説明しておこう。アセンブリの名前は4つの部分からなるが、それを表現する文字列形式が定められている。実はすでに登場しているのだが、それはこういうものだ。

System.Xml, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

 簡易名、バージョン、カルチャ、公開キー・トークンを並べて、カンマで区切って書く。なお、これらは原則的に省略できないことに注意して欲しい。例えばカルチャ中立だからといって、上記のアセンブリを次のように書くことはできない。

System.Xml, Version=1.0.3300.0, PublicKeyToken=b77a5c561934e089

 また、厳密名付きアセンブリではないので、公開キー・トークンがないときにも、次のような書き方はできない。

util, Version=1.0.0.0, Culture=ja-JP

 これらは次のように省略せずに書かなくてはならない。

System.Xml, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

util, Version=1.0.0.0, Culture=ja-JP, PublicKeyToken=null

 表示名を省略して書くと、その部分が設定されていない(neutralやnull)ということとは違う意味を持ってしまう。そのため、neutralやnullは明示的に書かなければならない。

今回のまとめ

 アセンブリの名前は4つの部分からなるデータ構造である。アセンブリの名前に公開キーが含まれている場合にそれを厳密名といい、その名前がついているアセンブリを「厳密名付きアセンブリ」と呼ぶ。厳密名付きアセンブリでないアセンブリを作成することも可能だが、CLRのさまざまな能力が利用できなくなってしまうので注意が必要だ。

 また、アセンブリの名前をほかのアセンブリから参照するときは、公開キーではサイズが大きすぎるので、そこから生成した小さな(8byte)トークンを利用する。これは公開キーではないので、署名の検証には使えないし、トークンから公開キーを再現することもできない。だが、ある公開キーのトークンは必ず同じ値になり、しかも公開キーのトークンはめったに重複しないことが確認されているので、公開キーの代わりにアセンブリの名前の一部として使われている。自分については公開キー全体を保持しているが、他人のアセンブリについてはトークンしか保持していないということに注意して欲しい。

 次回は、いよいよアセンブリをロードするプロセスを解説する。今回の解説で、アセンブリの名前にはファイル名、パス、URLなどが一切含まれていないことが分かっただろう。それではこのアセンブリの名前から、どうやってロードするファイルを探し出すのか、次回はその手順を解説することにしよう。End of Article


 INDEX
  解説 インサイド .NET Framework [改訂版]
  第2回 アセンブリのアイデンティティ
    1.アセンブリの名前
    2.厳密名とアセンブリ
    3.署名のないアセンブリ
    4.遅延署名したアセンブリを試す
  5.アセンブリの名前の参照
 
インデックス・ページヘ  「解説:インサイド .NET Framework [改訂版]」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間