EternalWindows
ファイル署名 / ファイルと署名

インターネット上などで公開されているファイルが何者かに改ざんされていないか、 もしくは想定していた相手から公開されたファイルであるかを特定する技術として、 署名は非常に重要な位置付けです。 ファイルに署名がされていれば、プロパティからファイルが改ざんされていないかを確認できますし、 署名がない場合は、そのファイルの公開元を信頼しなければよいことになります。 このような事情は、WindowsVistaから登場したUACによってさらに表面化し、 ファイルの実行時に本当に実行しても問題ないかをユーザーに通知するまでに至りました。 この事から、ファイルに署名をする技術を取得することは非常に重要といえます。

UACが有効であり、実行ファイルに"install"や"setup"などの文字列が含まれている場合には、 上記のようなダイアログが表示されることになります。 対象のファイルに署名が格納されてない場合、 上記のように不明な発行元と表示されてしまいますから、 実行には少々戸惑う部分もあるかもしれません。 署名が格納されている場合にもダイアログが表示されることになりますが、 そこには正しい発行元が記述されることになるので、 安心してファイルを実行することができます。

ファイルに署名が格納されている場合、その署名に含まれている証明書から そのファイルが誰によって提供されているかが分かるわけですが、 それを信頼できるかどうかはまた別の問題となります。 これは、証明書の内容を信頼するためには、 その発行者の証明書がルートCAとしてインストールされていなければならないからです。 このため、たとえ署名が格納されていても、それを信頼できない場合は、 先に述べたUACの問題は回避することができません。 署名されたファイルはプロパティとして「デジタル署名」を持ちますが、 署名が信頼できない場合は次のように警告が表示されることになります。

このような警告は、署名に自己署名入り証明書を含めた場合に表示されることがあります。 自己署名入り証明書というのは、自分で自分用に発行した証明書ですから、 それが他のコンピュータ上に既にインストールされていることはありません。 よって、他のコンピュータ上では、デフォルトで信頼されることはありません。 ローカルコンピュータ上では、作成した自己署名入り証明書を ルートCAに自分でインストールすることができますから、 上記のような警告を表示しないようにすることができます。

格納した署名に警告が表示される例には、原因を特定しにくいものもあります。 たとえば、次のような警告が挙げられます。

これは、ローカルコンピュータ上で署名を格納したファイルを、 他のコンピュータ上で確認した結果です。 警告が示す通り、署名には証明書が含まれておらず、 それ故に証明書を表示することもできないわけですが、 実はローカルコンピュータ上では警告が表示されず、証明書を表示することができます。 これは署名には必ず、署名時に利用した証明書のID(SerialNumberとIssuer)が含まれるからであり、 そのIDを持つ証明書が署名から検索できない場合、ローカルの証明書ストアを検索する仕組みになっているからです。 ローカルコンピュータ上の証明書ストアには署名に使った証明書があるはずですから、 ローカルコンピュータ上に限っては、署名に証明書が含まれているように見えるわけです。 このような問題を発生させないためには、署名時に格納したい証明書を忘れずに指定しなければなりません。

アプリケーションからファイルに署名するには、主に次の3つの方法が考えられます。

1, SIP関数の利用
2, MakeCert Functionsの利用
3, CryptUIWizDigitalSignの利用

1の方法は、署名の構造を理解し、それを明示的に作成しなければならないため、 手順としては非常に複雑になります。 また、CryptMsgOpenToEncodeを始めとするLow-Level Message Functionsの知識も前提となります。 しかし、本章ではファイル署名の本質を理解するためにも、SIP関数の利用から取り上げることにしています。 2と3の方法については、内部的に1の方法を利用しており、 1の方法の難しさを隠蔽しています。 特に3の方法は、GUIによる署名にも対応した優れた方法です。

Authenticodeについて

Authenticodeとは、Microsoftによって規格された署名形式であり、 一般にファイルに格納されている署名は、このAuthenticode形式となっています。 Authenticodeは、PKCS #7におけるSignedData型の形式とほぼ同一ですが、 コンテンツのデータがspcIndirectDataContextという独自の形式になっているのが特徴です。 それ以外の部分については、SignedData型の形式と同一であるため、 SignedData型と同じように証明書や属性といったデータを含むことができます。 Authenticode署名に含まれる証明書には、コード署名という拡張鍵用途が含まれていることが望まれます。

署名が何に対して適応されているのかを把握することは、非常に重要といえます。 たとえば、ファイルに対しての署名であれば、 その署名はAuthenticode署名のことを指していると考えることができますが、 通信データに対しての署名であれば、それはAuthenticode署名ではありません。 その署名は、PKCS #7におけるSignedData型であるかもしれませんし、 CryptSignHashで取得した値を独自にフォーマットしたものかもしれません。 本章で用いられる署名という言葉は、原則としてAuthenticode署名の事を指しています。



戻る