解説

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

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

吉松 史彰
2003/07/02

Page1 Page2 Page3 Page4 Page5

署名検証機能の無効化

 早速、遅延署名したアセンブリを作って、それを利用するコードを書いてみよう。例えば次のようなコードからアセンブリを作る。

using System.Reflection;

[assembly: AssemblyVersion("1.0"), AssemblyKeyFile("fumiakiypublic.snk"), AssemblyCulture(""), AssemblyDelaySign(true)]

public class Util2 {
    public string Method() {
        return "Hello@IT";
    }
}
遅延署名したアセンブリを生成するサンプル・コード(util.cs)

 これを次のコマンドでコンパイルする。

% csc /t:library util.cs

 util.dllというファイルだけで構成されるシングル・モジュール・アセンブリが作成された。今度は、これを利用するコードを書いてみよう。

class User {
    static void Main() {
        Util2 u = new Util2();
        System.Console.WriteLine(u.Method());
    }
}
上記のアセンブリを利用するサンプル・コード(user.cs)

 これを次のコマンドでコンパイルする。

% csc /r:util.dll user.cs

 お見事! コンパイルできたはずだ。ここで、出来上がったuser.exeをildasm.exeで確認してみると、次のようにuser.exeがutilアセンブリを参照している様子を確認できる(抜粋)。

.assembly extern util
{
  .publickeytoken = (BA 69 B5 76 33 AC EE E8 )           // .i.v3...
  .ver 1:0:0:0
}
user.exeがutilアセンブリを参照している様子を逆アセンブラildasm.exeで確認する(抜粋)

 実際の値は、読者の公開キーに対応する値になるので上記とは異なるはずだが、参照できていることは確認できるだろう。

 ではこれを実行してみよう。コンソール・プログラムなので、コマンドラインでuser.exeを実行する。すると、次のようなエラーになってしまう。

% user.exe

ハンドルされていない例外 : System.IO.FileLoadException: アセンブリ 'util' の厳密な名前の検証に失敗しました。
ファイル名 : "util"
   at User.Main()
作成したuser.exeを実行したときに表示されるエラー

 これはどういうことか? 共通言語ランタイム(CLR)は、厳密名付きアセンブリをロードするときには、ほとんどの場合にロードする直前に署名の検証を行う。つまり、インストールされたアセンブリが、開発者が秘密キーで署名をしたあとに改ざんされていないことを確認するわけだ。ところがここで作ったアセンブリは遅延署名しているので、まだ秘密キーで署名されていない。にもかかわらず厳密名を持っているので、CLRは署名の検証を行い、改ざんされたとみなしてアセンブリをロードしてくれないのだ。

 これでは結局開発作業が進まないので、遅延署名したアセンブリは一時的に署名の検証を無効にする必要がある。これもsn.exeで行うことができる。

% sn.exe -Vr util.dll

 sn.exeに“-Vr”オプションとアセンブリのマニフェストを持っているファイル名を指定すると、そのアセンブリに対しては署名の検証を行わないようになる。何だかセキュリティ・ホールを作り出しているような気がしてしまうが、これはあくまでも開発中の一時的な処置だ。

 これでもう1度user.exeを実行してみると、今度はきちんと実行できるはずだ。

% user.exe
Hello@IT
遅延署名機能を一時的に無効化してuser.exeを実行する

 アセンブリの厳密名が変わらない限り、“sn.exe -Vr”は1度だけ行えばよい。アセンブリをビルドするたびにやり直す必要はない。ただし、アセンブリの厳密名とは、簡易名だけではなくバージョン、カルチャ、公開キーが含まれていることに注意しなければならない。バージョンを変えてしまったりすると、“-Vr”はもう1度やり直しだ。ちなみに、Visual Studio .NETのプロジェクトには、デフォルトでAssemblyInfo.cs(Visual Basic .NETの場合にはAssemblyInfo.vb)というファイルが作られている。このファイルには、以下のとおりバージョン番号がデフォルトで指定されている。

[assembly: AssemblyVersion("1.0.*")]

 こうなっていると、バージョン番号はビルドするたびに変わってしまうので注意が必要だ。この場合、ビルドするたびにバージョン番号が“1.0.xxx.yyy”になり、xxxとyyyの値がどんどん変わってしまう。そうなると“-Vr”はそのたびにやり直しである。Visual Studio .NETを使っている場合には最後の“*”は取り除いておいた方がいいだろう。

遅延署名アセンブリへの署名

 さて、開発が完了して出荷プロセスに入ったら、今度こそ本当にバルマーCEOに承認をもらって秘密キーで署名しなければならない。アセンブリをインストールするお客さまは、決して“sn.exe -Vr”などやってはくれない(し、やってはいけない)からだ。何とか30個ほどハンコをもらって秘密キーを入手できる体制になったら、再びsn.exeの出番だ。今度は“-R”オプションで署名を行う。

% sn.exe -Rc util.dll CspContainer

 これでutilアセンブリは正しく署名された。あとはzipファイルに固めるなりCDに焼くなりして配布されるのを待つばかりだ。なお、あらかじめコンパイルしてあるuser.exeを再度コンパイルする必要はない。user.exeはもともと公開キーしか参照していないので、署名されようがされまいが、マニフェストに記述される内容には変化はないからだ。

署名検証機能の再有効化

 アセンブリはすでに正しく署名されているので、utilアセンブリに対する署名検証機能を再度有効化する必要がある。最後にもう一度sn.exeの出番がある。

% sn.exe -Vu util.dll

 “-Vu”オプションで署名検証機能を有効化する。なお、“-Vx”を使えば、これまでに無効化したアセンブリの署名検証機能をすべて破棄して、デフォルトの状態(すべての厳密名付きアセンブリが検証される)に戻すことができる。


 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 記事ランキング

本日 月間