Firefox 3ではじめる拡張機能開発

第8回電子署名済みアップデートマニフェストを用いた拡張機能の配布

前回「Firefox 3での自動更新のセキュリティ的な制約」で解説したように、httpsプロトコルでの暗号化通信に対応していないWebサーバで拡張機能を配布するには、⁠自分で作成したアップデートマニフェストへ電子署名を施して拡張機能を配布する」必要があります。今回はこの手順について解説します。

なお、実際に作成したインストーラおよびアップデートマニフェストは、下記URLから入手可能です。

手順の概要

この方式では、具体的にはインストールマニフェストとアップデートマニフェストに対して以下の3つの作業を実施します。

  • (1) インストールマニフェストへ公開鍵を追加する
  • (2) アップデートマニフェストへインストーラのハッシュ値を追加する
  • (3) アップデートマニフェストへ電子署名を施す

すると、以下のような仕組みにより安全な自動更新が可能となります。

  • アドオンマネージャで「更新を確認」する際、インストールマニフェスト中に記載された公開鍵と、安全ではない通信経路(httpプロトコルのURL)から取得したアップデートマニフェスト中の電子署名とを照合し、アップデートマニフェストの正当性(通信経路の途中で改ざんされていないこと)を検証する。
  • アドオンマネージャで「更新をインストール」する際、アップデートマニフェスト中に記載されたインストーラのハッシュ値と、実際にダウンロードしたインストーラから算出したハッシュ値とを照合し、そのインストーラの正当性を検証する。

McCoyのインストールと公開鍵・秘密鍵のペア生成

「手順の概要」で示した作業は「McCoy」と呼ばれるアプリケーションを使用することで比較的楽に行えるようになります。McCoyは下記URLのページの「McCoy のインストール」から入手可能です。

McCoyを初めて起動すると、マスターパスワードの入力を求められます。McCoy起動後、⁠Create」ボタンをクリックすると、⁠Create a New Key」ダイアログが表示されます。ここに適用な名前(例えば「test⁠⁠)を入力すると、新しい公開鍵・秘密鍵のペアが生成されます図1⁠。一度生成した公開鍵・秘密鍵のペアは、今後もずっと同じものを使い続ける必要があります。したがって、公開鍵・秘密鍵のペア生成の手順は、一度だけ実施すればかまいません。また、作成した公開鍵・秘密鍵のペアを、他の拡張機能に対して使いまわしても問題ありません。

図1 McCoyでの公開鍵・秘密鍵のペア生成
図1 McCoyでの公開鍵・秘密鍵のペア生成

インストールマニフェストへの公開鍵追加

続いて、先ほどMcCoyで生成した公開鍵・秘密鍵のペアを選択し、右クリックメニューの「Copy Public Key」から公開鍵の値をリップボードにコピーします図2⁠。さらに、既に作成済みのインストールマニフェストへ、リスト1のように<em:updateKey>{公開鍵の値}</em:updateKey>という行を追加します。

図2 McCoyで公開鍵の値をクリップボードへコピー
図2 McCoyで公開鍵の値をクリップボードへコピー
リスト1 インストールマニフェストの修正(例)
<?xml version="1.0"?>

<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">

  <Description about="urn:mozilla:install-manifest">
    <em:id>taghelper@xuldev.org</em:id>
    <em:type>2</em:type>
    <em:name>Tag Helper</em:name>
    <em:version>0.8</em:version>
    <em:description>Generates bookmark tags from the selection.</em:description>
    <em:creator>Your Name</em:creator>
    <em:homepageURL>http://www.xuldev.org/misc/sd.php</em:homepageURL>
    <em:updateURL>http://some-server/taghelper/update.rdf</em:updateURL>
    <em:updateKey>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCf+spGKCACaOJLeU8pEAIzdr7ipw393H5cU09OXNcKAoeVNGa4bx9cTW9xh08WOxAI8M2bhsusLk+TJ6IntOyIcF2L5W52EnCHmS/UtP8Cudk215L5lC2NjbeeCAw+qbyQY6shM4LZdBz0/amFln3go+7/2NfyxEMWBNkFlTGErQIDAQAB</em:updateKey>
    <em:localized>
      <Description>
        <em:locale>ja</em:locale>
        <em:name>タグヘルパー</em:name>
        <em:description>選択範囲からブックマークのタグを生成します。</em:description>
        <em:creator>あなたの名前</em:creator>
      </Description>
    </em:localized>
    <em:targetApplication>
      <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
        <em:minVersion>3.0</em:minVersion>
        <em:maxVersion>3.0.*</em:maxVersion>
      </Description>
    </em:targetApplication>
  </Description>

</RDF>

インストールマニフェストの修正が完了したら、第7回で解説した手順でXPI形式のインストーラを再作成します。なお、前述の通り公開鍵・秘密鍵のペアは今後同一のものを使い続けるので、今後新しいバージョンのインストーラを作成する際に<em:updateKey>タグの値を変更する必要はありません。

アップデートマニフェストへのインストーラのハッシュ値追加

次に、さきほど作成したインストーラのSHA-1ハッシュ値を算出します。SHA-1ハッシュ値の算出方法には、Windows/Linux用ソフトウェア「bkhashes⁠⁠、Firefox拡張機能「MDHashTool⁠⁠、Cygwinの「sha1sum」コマンド、PHPの「sha1_file」関数などがあります。筆者の環境にはPHPがインストールされているので、コマンドプロンプトからリスト2のようにしてSHA-1ハッシュ値を算出しています。

リスト2 PHPの「sha1_file」関数を使ったSHA-1ハッシュ値の算出
php -r "echo sha1_file('c:\\work\\taghelper\\taghelper.xpi');"

SHA-1ハッシュ値を算出したら、第7回リスト3の形式で作成したアップデートマニフェストに対して、リスト3のように<em:updateHash>sha1:{SHA-1ハッシュ値}</em:updateHash>という形式でタグを追加します。なお、後の動作確認にてアドオンマネージャに更新を検出させるため、あえて<em:version>タグの値を「0.8」ではなく「0.8.1」としています。

リスト3 アップデートマニフェストの修正(例)
<?xml version="1.0"?>

<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">

  <Description about="urn:mozilla:extension:taghelper@xuldev.org">
    <em:updates>
      <Seq>
        <li>
            <Description>
            <em:version>0.8.1</em:version>
            <em:targetApplication>
              <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>3.0</em:minVersion>
                <em:maxVersion>3.0.*</em:maxVersion>
                <em:updateLink>http://www.xuldev.org/misc/sd/taghelper-0.8.xpi</em:updateLink>
                <em:updateHash>sha1:8d6769c9bca0bda73727770ba1bbaf66409263b8</em:updateHash>
              </Description>
            </em:targetApplication>
          </Description>
        </li>
      </Seq>
    </em:updates>
  </Description>

</RDF>

注意点すべき点として、SHA-1ハッシュ値は、インストーラのファイルが1バイトでも違えばまったく異なる値となりますので、インストーラを作成したらその都度ハッシュ値の追加をしなおす必要があります。

アップデートマニフェストへの電子署名

アップデートマニフェストへの電子署名を施す前に、現在の状態のアップデートマニフェストをファイル名「update.rdf.bak」などでバックアップしてください。

McCoyで生成した公開鍵・秘密鍵のペアを選択し、⁠Sign」ボタンをクリックして、先ほど作成したアップデートマニフェストのファイル「update.rdf」を選択します図3⁠。すると、アップデートマニフェストの内容がパースされ、リスト3のように電子署名を表す<em:signature>タグが追加されます。

図3 McCoyでの電子署名
図3 McCoyでの電子署名
リスト4 電子署名を施したアップデートマニフェスト(例)
<?xml version="1.0"?>
<RDF:RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#"
         xmlns:NC="http://home.netscape.com/NC-rdf#"
         xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <RDF:Description RDF:about="rdf:#$3b.rF3"
                   em:version="0.8.1">
    <em:targetApplication RDF:resource="rdf:#$6b.rF3"/>
  </RDF:Description>
  <RDF:Description RDF:about="rdf:#$6b.rF3"
                   em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
                   em:minVersion="3.0"
                   em:maxVersion="3.0.*"
                   em:updateLink="http://www.xuldev.org/misc/sd/taghelper-0.8.xpi"
                   em:updateHash="sha1:8d6769c9bca0bda73727770ba1bbaf66409263b8" />
  <RDF:Seq RDF:about="rdf:#$2b.rF3">
    <RDF:li RDF:resource="rdf:#$3b.rF3"/>
  </RDF:Seq>
  <RDF:Description RDF:about="urn:mozilla:extension:taghelper@xuldev.org"
                   em:signature="MIGTMA0GCSqGSIb3DQEBDQUAA4GBAI+e5XvP8Q/viijwVWbC30MvwM4Ohstm5hqUqfkhjmZCsWcIUaux1XPi2r+/keAN+XxTYV4oaQvcP9OSeOzEQNuxwTNUDP5iHmDfRjpEfQHNI5X4QYHmNqlcHTm2loQzQjq1fQd1vUSRdq1WP9/NELuBqpnzC6abb1+iK+WK978q">
    <em:updates RDF:resource="rdf:#$2b.rF3"/>
  </RDF:Description>
</RDF:RDF>

なお、McCoyによって電子署名が施されたアップデートマニフェストは、XMLの構造が少し複雑になります。しかし、このファイルを直接編集しないでください。アップデートマニフェストを編集する場合は、バックアップした「update.rdf.bak」からアップデートマニフェストの内容をいったん元に戻し、内容を修正後再びバックアップしてから上記手順で電子署名を施してください。

Webサーバでの公開

アップデートマニフェストとインストーラを、それぞれリスト1の<em:updateURL>で示したURL、リスト3の<em:updateLink>で示したURLでダウンロード可能となるよう、Webサーバ上に公開します。なお、Webサーバからインストーラをダウンロードする時、WebサーバはHTTPレスポンスヘッダ「Content-type: application/x-xpinstall」を返すよう設定する必要があります。詳しくは下記URLの「拡張機能 XPI の作り方」を参照してください。

Extension Packaging - MDC
URLhttp://developer.mozilla.org/ja/Extension_Packaging

動作確認

実際にアドオンマネージャにて更新確認と新しいバージョンがインストール可能であることの動作確認を行います。インストーラの動作確認用のプロファイルへタグヘルパーが既にインストールされている場合は、まず削除(アンインストール)してください。その後、以下の3点を確認してください。

  • リスト3の<em:updateLink>で示したURLをFirefoxのロケーションバー入力すると、タグヘルパー(バージョン0.8)のインストールが正常に行われる。
  • タグヘルパー(バージョン0.8)をインストール後、アドオンマネージャで「更新を確認」すると、図4のようにタグヘルパーの更新(バージョン0.8.1)が検出される。
  • アドオンマネージャにて「更新をインストール」ボタンをクリックすると、正常にインストールが実行される。
図4 タグヘルパーの更新を検出
図4 タグヘルパーの更新を検出

なお、今回は動作確認として、アップデートマニフェスト側はバージョン0.8.1、実際のインストーラはバージョン0.8としています。したがって、上記手順の自動更新後に再び「更新を確認」すると、再度タグヘルパーの更新(バージョン0.8.1)が検出されることになります。

まとめ

今回はおもにレンタルサーバなどで拡張機能の配布をする方を対象として、アップデートマニフェストへ電子署名を施して安全な自動更新を可能にする方法を解説いたしました。今回で全8回にわたる連載「Firefox 3ではじめる拡張機能開発」は終了となります。どうもありがとうございました。

おすすめ記事

記事・ニュース一覧