Windows Vista を勧めてみる2006年06月01日 21時08分34秒

XP のトラウマ

Windows 2000 から XP へのアップグレードは、実に惨憺たるものであった。以下に、XP になって新しくなった事柄と、その弊害について、思いつく限り列挙してみようと思う。

  • GUI が刷新された。それは改悪と言うべきものであった。たとえばスタートメニューは煩雑になったし、コントロールパネルはカテゴライズが一部いまいち直感的でない (「管理ツール」が「パフォーマンスとメンテナンス」に隠れる、等) 為にクリック回数が増えた分不便になったし、IME はタスクバーの常駐アイコンに隠れてくれなくなってしまったし、エクスプローラのファイル検索機能もなんだかゴテゴテして手軽じゃなくなった (なんだよあのかわいくない犬っころのアニメーションは)。古くから Windows を使ってきたユーザーの多くは、新しくなった煩雑な GUI に慣れるのに多くの時間をかけたか、もしくはクラシカルな GUI として動作するよういろいろと設定を弄繰り回したはずだ。
  • リモートデスクトップ機能により、ネットワークを介して他のパソコンのデスクトップを操作できるようになった。但しホストになれるのは Professional Edition 以上のグレードの XP のみであり、大勢を占める Home Edition ユーザーには無関係の機能だったし、そうでなくても使っているのは本当にごく一握りのマニアか IT 技術者ぐらいだったんではないかと思う (テスト用途では確かに使えなくもない機能ではあるんだけれども)。そのくせ、こいつのポートを駆動するサービスである DCOM が持つ欠陥の為に大流行した MSBlast や Natch などの自動繁殖型ワームによる被害は Home Edition であっても食らわされまくったわけだ。
  • Home Edition は差別化のために、Windows ドメインサービスに参加できなくなった。知らないでこいつを大量導入したために、Windows ドメインサービスを用いて構築していた社内ネットワークが事実上破綻したなんて話も実はあったりする。まぁでもこれについてはそれ程「困った」という声も聞かれなかったわけで、如何に Windows ドメインサービスが無用なものかが証明されたと言う虚しい結果を露呈したに過ぎなかったわけではあるが。
  • DVD-RAM が標準でサポートされたが、当時事実上のデファクトスタンダードであったフォーマット形式である UDF 2.0x には読み込みしか対応しておらず、FAT32 でのアクセスが基本、という中途半端な対応であった。
  • Service Pack 2 にて行われた、あまりにも大きな変更。「本当の XP は SP2 からなのでは?」なんて囁かれるくらいに重要な変更が数多く行われたわけだが、それゆえに、一部のハードウェアではそのままでは上手く動作しないため、BIOS のファームウェア書き換えを余儀なくされたり、様々なトラブルに見舞われたりと、多くの混乱を招いた。

もっとも、SP2 登場以降の Microsoft は実に良く働いていると思うし、セキュリティーアップデートも非常にスムーズに行われるようになり、一般ユーザーにとってはどんどん安全に使える商品へと成長していっているように思う。また、近々リリースされる Internet Explorer 7 も、XP SP2 以降のみの対応とはいえ、セキュリティー面のみならず、CSS サポート、タブブラウジング、その他のアクセス性向上への計らいなど見るべき部分は多く、歓迎すべき成長を遂げようとしている。

また、ユーザー管理周りやログオンの手軽さ、コマンドプロンプトにおけるコマンド補完機能など、細かい点において利便性の向上が無いわけではなかった。

とはいえ、多くの消費者は、Windows XP によってもたらされたエクスペリエンスに辟易しており、また少ない機能向上と多くの改悪の為にお金を費やすのはバカバカしい、と思っているユーザーは少なくないのではないかと思う。あるいは、1~2 年待って Service Pack が更新されて十分に安定してから手を出した方がよい、と考える方も少なくないだろう。

Windows Vista にアップグレードする価値はあるか?

では、Windows XP から Vista へのアップグレードは、また同じように退屈なものとなるのだろうか? 確かに、本来一番の目玉のひとつであったはずの WinFS は先延ばしのような状況にされてしまったが、それでも、Windows Vista には多くの魅力的な新機能が追加されているという主張が、Microsoft のサイトには書かれている。

今回は、そのサイトに書かれている Windows Vista の機能について、おいらなりに解説してみようと思う。なお、ベータ版を触ったわけではないので、いくつか解釈に誤りがある可能性もある。鵜呑みにはしないで欲しい。

GUI の見た目、および技術的な変更

ユーザー エクスペリエンスのページでは、Windows Vista にて刷新される GUI について記述されている。

スタートメニューは、プログラムへのアクセスが近くなった分、XP よりは若干マシになったかもしれない。エクスプローラの GUI についてはなんとも言えないが。んで、Aero は一旦置いておいて、あと目に付く変更はタスクバーのサムネイルと、Windows フリップ、そして Windows フリップ 3D だと思う。

サムネイルはさておき、特に 3D 表示に関していえば、反感を持つ方も大いにいらっさるのではないかと思う。3D 描画は 2D 描画に比べると「処理が重い」という印象が強いからだ。よっぽどリッチな環境でもない限り、こうした機能が使いこなされることはなく、現行のマシンに Windows Vista をインストールする場合、結局はクラシカルな GUI に切り替えて使用することになるのではないかと考えている方も多いと思う。

この認識は、必ずしも正しくはない。ライブタスクバーや Windows フリップ、3D 表示などは、Windows Vista より導入される画面デザインモードである「Windows Aero」を使用する際に実現される。ここで、「Windows Aero」に関する Microsoft のサイトにおける説明を以下に引用する。

表示機能がより洗練された環境を備えた Windows Aero は、応答性と管理性を備え、これまで以上に簡単で確実な操作性を Windows ユーザーに提供します。

「管理性」とはまさに GUI デザインそのもののことだが、では、「応答性」とはどういうことか? 同じく Microsoft が、開発者向けに提示する資料、Windows Vista デベロッパー センター - エクスペリエンスを見てみよう。

Windows Vista には、安全で安定した新しいグラフィックス ドライバ モデルが導入されました。このグラフィックス ドライバ モデルには、グラフィックス プロセッサ ユニット (GPU) の継続的な使用を可能にするフォールト トレランスが組み込まれており、これによりオペレーティング システムおよびアプリケーションで豊かなグラフィックスが実現されます。このドライバ モデルの GPU メモリ マネージャおよびスケジューラを使用すると、GPU を使用する複数のグラフィックス アプリケーションを同時に実行できます。

Direct3D10 としても知られる Windows Graphics Foundation 2.0 (WGF) は、この新しいドライバ モデル上に構築されていますが、ドライバ モデルからは独立しています。このアプリケーション プログラミング インターフェイス (API) を使用して、アプリケーションから魅力的な次世代シネマトグラフィックを実現できます。また、並列化が容易でより汎用な、アプリケーション用の GPU (GPGPU と呼ばれる) 上で利用できる、非常に強力な演算能力を利用することもできます。この機能は画像処理などに活用できます。

Direct3D という言葉が出てきた。これは従来、高度なマルチメディア機能を提供する SDK として扱われてきた技術で、主にゲームなどに使われてきたものだ。従来 Windows の GUI は GDI と呼ばれる 2D ベースの描画エンジンを用いて描画されており、これは後方互換性の重視された描画方法であって、パフォーマンスは決して良くはなかった。また、アプリケーションが行う表示の内容を OS 側では管理できないため、アプリケーションの上に他のウィンドウが重なると、重なった部分が再び上に表示されるたびに、アプリケーション側で描画のし直しを行う必要があった。

DirectX を用いてゲームなどのプログラム開発を行った経験のある方ならお分かりかと思うが、同じ 2D での描画を実現するにしても、GDI 上で普通に描画を行うよりも、3D 空間上に配置するサーフェス (平面領域) 上にテクスチャマッピング (3D 空間上の面に 2D の絵を貼り付ける描画方法) で描画を行った方が、描画は高速に行われることが多い。また、3D ならば、アプリケーションのウィンドウごとに複数のサーフェスを用意すれば、用意したサーフェスの数だけ画面の表示内容を保持することができ、このサーフェスの奥行き方向の位置を置き換えるだけでウィンドウの切り替えは実現するため、ウィンドウの切り替え操作自体も高速且つ滑らかになる。

実際に Windows Vista β2 を試用したレポート記事がある。注目すべき記述を以下に引用する。

そうした3Dエンジンによる描画のメリットは、1つにはWindowsデスクトップやアプリケーションなどで3D表示が行なえることだ。たとえば、Windowsキーとタブを同時に押すことで現在デスクトップに開かれているウインドウが3D表示され、タスクスイッチとして利用できる機能(Flip 3Dと呼ばれる)などが実装されているほか、従来のWindows XPのように、動画再生中にそのウインドウを動かすと後ろに画面のゴミが残ったりしたが、Windows Vistaではスムーズに画面が表示される

従来の Windows において、ウィンドウ操作にストレスを感じることが少なからずあったという方は、Windows Vista への乗り換えを検討する価値は十分にあると思う。

なお、Windows Aero は Windows Vista をインストールしたマシンすべてにおいて満足に駆動するものとは限らず (上記のような動作は最低でも DirectX 9 が動作するマシンでなければ実現できないだろう…ここ 2~3 年の間に新調したマシンならば恐らくは問題ないだろうが)、またこのモードは使用しないように設定することもできるようなので、たとえば Vista 以降に登場するプログラムが、非 Aero 環境をまったく考慮しない作りになる (WM_PAINT メッセージハンドラを書かない為に、非 Aero 環境で再描画が行われない、とか) と言うことはまずないと思う。その辺の開発スタイルの変革が現実的になるのは、もうちょっと先の話なのではなかろうか、と思われる。また、描画が早くなるのはウィンドウ操作を始めとした GUI 周りと、Aero に最適化された WGF を用いたアプリケーションだけであって、従来の GDI で書かれたアプリケーションがそのままでいきなり高速化されるということも多分ないと思う (GDI 自体の中身が Direct3D 互換で置き換えられていたら話は別だけど)。

セキュリティ関連

セキュリティのページでは、セキュリティ関連の記述が行われている。

全体的に見て、XP SP2 に毛が生えた程度だといえると思う。家庭のユーザーが、ちゃんと子供に別の ID を与えることを前提にしている辺りも含めて (そんな家庭って少数派なんじゃないの?)。

検索機能

検索と整理のページでは、主にデスクトップ検索について記述されている。

デスクトップ検索は本来、WinFS がいかに素晴らしい技術であるかを証明するために用意された機能、という位置づけになるはずだったが、とりあえず基礎技術としての WinFX は後回しにした状態で、検索機能だけがグレードアップするようだ。スタートメニューから PC 全体を手早く検索できるほか、検索を助けるための属性情報をファイルに追加・編集することができるようになる。例えば、飼い猫 (仮に名前を「ミーコ」としよう) が映っている写真画像ファイルにすべからくキーワード「ミーコ」を設定しておけば、デスクトップ検索で「ミーコ」と入力するだけで、PC に保存されているすべての飼い猫画像の一覧が得られる、というわけだ。

ネット上を徘徊して壁紙画像を拾いまくっているような人は、こうした機能はそれなりに重宝するんではないかと思う。

IE7

Windows XP SP2 向けにも配布される IE7 だが、Vista では標準でついてくる。これについてはこちらのページを見たほうが良いかと思われる。タブ、RSS フィード、CSS 周り等、いろいろな面で IE6 よりかなりマシになっている。

。。。WinFS のバックポートなんてどうでもいいから、こっちを Windows 2000 向けにバックポートしてくれ。

Windows サイドバーとガジェット

いろいろと鬱陶しいものがついてくるようだ。

電源周り

パフォーマンスのページでは、主に電源周りとメモリ周りについて記述されている。

まず電源周りだが、スリープモードというのが追加される。ん? 今まではなかったんだっけか? とか思ったが、読んでみたらどうやら従来のスタンバイモードとレジューム機能を合体させ、スタンバイモードの復帰の速さとレジューム機能の安全性をいいとこ取りしよう、というもののようだ。実行時のシステムの状態はメモリとハードディスクの両方に保存され、通常はメモリから素早く復帰できるし、停電とかがあってもハードディスクから復帰できるから安心よ、ということらしい。UPS 要らず? そういうわけでもないか。ノート PC の場合は保存先をバッテリの残量を見ながら適宜切り替えるようになるみたいね。

長時間電源入れっぱなしにすることが多いが消費電力も気になるという人にはうれしい機能、なのかな。

メモリ周り

同じページより。スーパーフェッチについては、まぁ良いものなのだと期待しておこう。優先度設定スキーマってのがどの程度有効に動作してくれるものなのかは知らんが。

それよりも、今回あまり宣伝されていないながら、実は何気に目玉なんじゃないかと思うのが、外部メモリデバイス機能である。USB フラッシュメモリを仮想的なメインメモリとして追加できるというのだ。

恐らく動作の仕組みとしては、いままで HDD にスワッピングを行っていた仮想メモリ領域を、USB ストレージに対して行うことができる、というようなものなのだと思う。HDD のスワッピングが起こると、どうしても動作が重くなってしまうばかりでなく、ディスクの読み書きが頻繁に行われるため、読み取りヘッドが磨耗しやすくなり、HDD 自体の寿命を縮める要因にもなっていた (もちろん、USB フラッシュメモリもあまり頻繁に読み書きを行うと HDD 以上に寿命を早く縮めることになるが、故障時に失われるデータ資産のコストを考慮すると、心象的には HDD の磨耗よりよっぽど健全だと思う)。小型のノート PC などで、USB 2.0 が利用できるマシンならば、意外と重宝する機能なのではないだろうか。

ハイブリッド HDD は、、、まぁ、またマシンを新調することがあれば使おうかな。

バックアップ関連

バックアップのページでは、システムの復元やファイルのバックアップについて記述されている。

システムの復元については、なんだかイマイチよくわからんが、システム周りのファイルや設定について履歴管理が強化された、ってことなのかな?

バックアップは、そもそも今まで OS の機能として使っていたという人は Windows ユーザーではあんまりいないんじゃないかっていう気もしなくもないわけですが (ふつーにバックアップを取るフォルダをそのまま CD-R とかにコピー、てな感じで)、今回バックアップ先に USB ストレージとかを選択できるようになり、その上スケジュール登録できるようになったと言うことで、少しは使う人も出てくるのかな、って感じ。まぁマシンをサーバ用途に使うんでもない限り、バックアップのスケジューリングってあんまり意味のない機能のような気もするけど (マシンの電源を四六時中入れっぱなしにする一般ユーザーは少数派)。

ボリュームシャドウコピーは、うっかりミスとしての上書きコピーから元々のファイルを復元できるわけで、これはかなり便利かもしれんね。

ネットワーク接続

ネットワーク接続のページ。ネットワーク設定が USB フラッシュメモリに保存できるってのはおもしろいかな。ネットワークマップもそれなりに便利そう。

Windows SideShow

Windows SideShow のページでは、Vista 時代に新たに登場するとされている、ポータブルデバイスの補助ディスプレイ機能について記述されている。マシンを起動しなくても、このディスプレーからスケジュールやらメールやらが参照できるとのこと。ケータイとかで十分じゃん、とか言われそうだが、参照するデータは当然ラップトップ PC と共有しているわけで、データの管理に一貫性があるという点ではそれなりに便利なんじゃないかと思う。とはいえ、そもそもノート PC を仕事で使わない人や、未だに Lotus Notes とか使ってるような方々には無用の長物になるんだろうなぁ。。。

まとめ

とまぁそんな感じでやたらと長くなってしまったわけですが、結論としては、まぁ 2000 から XP へのアップグレード時に感じたよりは、マシな機能向上になっているんではないかと思う。特に描画周りは、後々の Windows アプリケーション開発スタイルに大きな影響を与えかねない部分であり、バージョン間のシェア移行が進めば、旧バージョンの Windows では特定のアプリケーションで動作にハンディキャップが生じる可能性もないとも言い切れない。経済状況が許すならば、様子を窺いつつ移行を検討してみても良いのではないかと思うし、急ぎでなければ、新規 PC の購入も Vista の登場まで待ったほうが賢明かもしれない (特にノート PC)。

# ていうか今から予約受け付けてるのかよ。。。(;´Д`)

各種アフィリエイト - 5月成績2006年06月01日 21時50分32秒

(´・ω・`)
  • Google AdSence: 2848 pv、3 クリック。収益額は USD 1.12 。
  • Amazon Associate: こちらは四半期ごとの成績しか見れないのですが、これまでで直リンクのクリック数は 42 、売り上げは 0 。

相変わらず、儲かっておりません。てゆか、本来主力であるはずの記事末尾の位置から外された Google AdSence が、先月までよりもクリック数を稼いでいるってのが微妙。。。まぁ 1 クリックも 3 クリックもどんぐりの背比べだけどな。

ちなみに Amazon のクリック内訳は、「秋葉やすこ アキバ系」が一番多くて 17 クリック。ついで「きのこちゃん」が 14 クリック、「MEZZO ACTION.1 (初回生産限定版)」が 2 クリック。あとはあっても 1 クリックずつ。

秋葉やすこの人気はよくわかったが (だから買えよとw)、それにしても、みんな意外とサイドメニュー見てるのね。

堀江貴文拘置所ダイエット2006年06月04日 08時24分15秒

そうか大麦か。ていうか、やっぱり食生活は重要なんだなぁと再認識。

チーズは内臓脂肪を減らすらしい2006年06月05日 11時58分28秒

メモメモ...∮(゚∇゚*)

ドロップダウンメニューのテスト2006年06月05日 14時49分10秒

ドロップダウンメニューを実現する HTML のサンプルを書いてみた。ソースはリンク先を参照。

おんなじようなことをやっているサイトってのは結構あるんだけど、マウスがサブメニューから離れてもサブメニューが閉じてくれなかったり、変なルールでサブメニューが閉じるようになっていたりと、いまいち操作感がしっくりこないサイトが多いように思う。

今回書いてみたサンプルのポイントは以下の通り。

  • メニューはリストを記述するタグ <ul><li> を用いて記述している。メニューはメニューアイテムの階層的なリストだよ、という考え方だわね。
  • メインメニューのアイテムにマウスカーソルが重なると、onMouseOver イベントハンドラが自前の openSubMenu 関数を呼んで、指定した ID の要素ブロックがサブメニューとして表示される。このとき表示されるブロックは、メインメニューのアイテムである <li> 要素の配下にある <ul> 要素であるため、このブロック上にマウスカーソルが重なっている間は、メインメニューアイテム (の配下の要素) 上にマウスカーソルが重なっているのと同じということになり、メインメニューアイテムの onMouseOut イベントは発生しない。マウスカーソルがメインメニューアイテムやサブメニューブロックのいずれからも離れると、メインメニューアイテムの onMouseOut イベントハンドラが呼ばれ、それが更に自前の closeSubMenu 関数を呼んで、指定した ID の要素ブロックであるサブメニューが非表示となる。
  • メインメニューアイテム <li> 要素のスタイルに position: relative; を、サブメニューブロック <ul> 要素のスタイルに position: absolute; を指定することによって、サブメニューの表示位置を、メインメニューアイテムの表示位置からの相対位置として指定することができる。

意外とシンプルに、あっさり作ることができた。Firefox、IE、Opera にて表示確認。IE 6.0 だと li:hover によるハイライト表示ができない (IE 7.0β ならできるが) のが微妙だけど、動作としては問題ないんじゃないかなと。

ウィンドウのテスト2006年06月11日 01時12分20秒

前回に引き続き、今度は HTML でページ上に表示するウィンドウのようなものを作ってみた。サンプルはこちら。ソースはリンク先で「ソースを表示」して参照してちょ。

Ajax の開発環境である TIBCO が Ajax 上で動作していたりAjax で動作するデスクトップ環境なんてものまで存在する昨今、ウィンドウ一つ作って見せたところで別にどってことも無いんだが、それなりにわかりやすいソースを示したサンプルともなるとあんまりないんじゃなかろかのーということで。実用化の再には折りたためたりサイズ変更できたり表示・非表示を制御できるようにしたりして、これまでポップアップウィンドウで実現しようとしていたようなサイトのサイドツール (ヘルプ表示とか、サイトマップとか、メッセンジャーとか) を作るのに応用すると面白いかもね。

今回のサンプルだが、JavaScript にて記述した部分をいじらなければ、以下のような HTML を追記することによって簡単にウィンドウを増やすことができる。

<div class="window" id="ウィンドウID">
  <div class="titlebar">
    ウィンドウタイトル
  </div>
  <div class="client">
    <!-- ...表示する内容... -->
  </div>
</div>

ウィンドウ ID はウィンドウごとに違う文字列を指定する必要があるだよ (ウィンドウの識別に使用している為)。

今回書いてみたサンプルのポイントは以下の通り。

  • ウィンドウのドラッグ移動を制御するコードを、オブジェクト指向で記述してみた (windowMove オブジェクト)。まぁ、結果的にはあんまりオブジェクト指向にした意味無かったけどな。つか、JavaScript って、オブジェクト指向言語なのよ。
  • スタイルシートに JavaScript による振る舞いを記述することはできないので、<body> 要素の onload メッセージハンドラから呼び出す自前の関数の中で、titlebar クラスの <div> 要素を拾い上げて、メッセージハンドラの設定などをやっている。
  • タイトルバー部分にマウスカーソルを合わせてボタンを押下すると、その <div> 要素の onmousedown メッセージハンドラから呼び出される処理の中で、動かそうとするウィンドウに結び付けられた windowMove オブジェクトを、変数 capturing_window にセットする。ドラッグ中のマウス移動、およびマウスボタン解放時のハンドラは、<div> 要素のものではなく document のものを使用し、ハンドラの中で変数 capturing_window を参照して、現在移動中のウィンドウとして識別。こうすることで、マウスを思いっきり素早く移動してもちゃんとウィンドウが付いてくるようになる。ウィンドウ移動中でなければ capturing_window には null が入る。
  • ウィンドウ移動中でも、通常のドラッグ操作によって行われる動作 (すなわち、テキストの選択) が行われてしまうことがある。これを防ぐため、以下の対策を行っている。
    • IE の場合: ウィンドウのドラッグを開始する際の onmousedown ハンドラの中で、document.onselectstart メッセージハンドラに return false; する関数をセットする。これによって、ドラッグ操作によるテキスト選択が禁止される。ドラッグ終了時の onmouseup ハンドラの中で、document.onselectstart メッセージハンドラに return true; する関数をセットすることで、テキスト選択が行われる状態に戻る。この手法は多くのサイトで紹介されているが、IE でしか動作しないため、これだけでは不十分である。
    • IE 以外の場合: ECMA-262 準拠の JavaScript 実装を備えたブラウザであれば、event.preventDefault() メソッドの利用が期待できる。このメソッドは、ハンドラを呼び出しているイベントが、本来デフォルトで行うべき動作を、行わせないようにしてくれる。ボタン押下時、およびドラッグ中にこのメソッドを呼び出しておくことによって、テキストの選択を行わないだけでなく、それまで選択されていたテキストの選択範囲を変更しないでおくことも可能だ。
  • ウィンドウを表す <div> 要素は、position: fixed;、すなわち (本物の) ウィンドウに対する絶対位置として実装している為、例えば画面をスクロールしても、ウィンドウの、ブラウザ表示領域に対する表示位置は変わらない (つまり、一緒にスクロールされない)。これは、今回のサンプルでは、6.0 以下のバージョンの IE 以外での動作となっている。IE 6.0 以下では、position: fixed; が使用できない為、<body> 要素の onload メッセージハンドラの中で、position: absolute; を使用するように書き換えている。
    ここで、そんなことせんでもスタイルシートを以下のように書いてしまえばいいではないか、という声が上がりそうなものなんだが、
    div.window {
        position:           fixed   !important;
        position:           absolute;       // IE 6.0 以下
    /* ... */
    
    この場合、position: fixed; で動作できるはずの IE 7.0β2 においても position: absolute; として動作してしまうようなので、敢えて JavaScript の中で書き換えるという手法を選んでみた (つまり IE 7.0 β2 は CSS の !important をこのケースでは無視してしまうということ?)。

今回も、Firefox、IE、Opera にて動作確認済み。さすがに、メニューと比べればかなり複雑な実装になった。実際には位置を動かせるだけでは実用にはならないので、実用レベルで実装するにはもっと複雑なコードになる。でも、ブラウザ間の動作の違いなどに対するノウハウは、ここまでの実装で大体吸収できてるんではないかな。

あともう一つ。先日からたびたび紹介している「JavaScript ビジュアルリファレンス」ですが、JavaScript のプロトタイプベースなオブジェクト指向言語としての性質についてはちっとも触れられていません。その他、言語仕様的な部分の説明についても、やはり不十分な感は否めないです。その辺の部分がしっかり書かれた参考書をこれから探してみようかなぁなどと思う次第。。。やっぱ O'REILLY かなぁ。

とりあえずそんな感じで。

# ぷーさんて まさにいまの おいらだね 字足らず。

サーバーを自由に弄れない環境でのセッションID生成2006年06月20日 10時50分51秒

あらまし

頼まれ仕事なのですが、こんな感じの Web スペース上で、「管理者だけが閲覧できるページ」を含む Web アプリを実現せなあかんちうことになりまして、もちろん基本認証とかも使えないので、CGI だけで認証機構を用意しないといけないのですが、その実現方法をどうしようかなぁというお話。

実は、既にプログラムは Perl で途中まで組まれていて、認証機構の実現で幾分か行き詰っている状態なのであります。重要なのは、信頼性の高いハッシュ関数と、暗号理論上安全な乱数の生成であり、これらは Perl の場合、前者は Digest::SHA かもしくは MD5、後者は Math::TrulyRandom といったモジュールを追加してあげれば確実に実現可能なわけですが、自分で設定できるサーバーを使うわけではないため、これらのモジュールを組み込んで使うことは不可能だったりするわけです。

# gcc をサポート、とあるので、各モジュールのソースをダウンロードして make まではできるのかもしれないけどね。それができれば CGI プログラムと同じ場所においておくことでとりあえず動かすことはできるけど。。。そもそも telnet や ssh が使えるわけでもないのにどうやって make を走らせるんだろう?

んで、一体どうしたもんかなぁという辺りをぐだぐだと考えてみるテストなのです。

ハッシュ関数

PHP3 が使えるので、PHP の md5() 関数を使うという手がある。Perl から PHP の関数を利用するには、例えばこんな風に書けばいいんじゃないかな。

my $digest = `php -r 'echo md5("$text");'`;

むしろプログラム自体を PHP で書け、という話もあるのですが。。。まぁ拡張子を「.php3」にすれば確かに PHP3 環境のテストもできるけどさぁ。

PHP を外から使うのがまどろっこしいと思うのであれば、あとは crypt 関数を利用する、という手もある。この手の無料 Web スペースや安価なレンサバなんかの場合、OS は大概 Linux だろうと思われるので、crypt がサポートする暗号方式もおそらく 64 bits DES 方式かと思われる。その場合、ハッシュ化できる文字列は最大 8 文字までなので、crypt 関数自体を複数回に分けで呼び出してあげる必要があると思う。あーマンドクセ('A`)

乱数

セッション ID を生成する基本的なやり方は、状況を識別できる情報 (ユーザー ID、時刻、その他必要に応じてシチュエーションを識別する記号) と、暗号理論上安全な乱数とを混ぜ合わせた文字列*1を、ハッシュ関数によって符号化*2する、というもの。十分に識別可能であり、また、十分に予測不可能であることが必要とされるわけです。

で、その肝心の乱数ですが、仮にサーバーの OS が Linux ならば、/dev/random/dev/urandom を使用することができます。例えば Perl で 64 bits (= 8 Bytes) の乱数列を得るには、以下のように記述することになります。

my $text;
open randin, "</dev/random"  or die 'Cannot use /dev/random';
read randin, $text, 8;
close randin;

Manpage を見ると、/dev/random はより安全だが、エントロピー・プールが空になるとブロックされてしまう、とある。実際に使ってみると分かるのだが、キーボードやマウスからの入力がないと、数バイト読み出しただけで処理はブロックされてしまう。ホスティングサーバーなどはヒューマン・インタフェースが接続すらされていない可能性が高いため、これでは使い物にならない。かといって、/dev/urandom では、ブロックはされないが、環境ノイズが十分に反映されない可能性があるため、決して安全であるとはいえないかもしれない。

ちなみに、PHP には mt_rand() という関数があり、普通に rand() 関数とか使うよりはマシっぽそうに見えるのだが、これが採用している擬似乱数生成法である Mersenne Twister暗号論的な擬似乱数ではないため、これだけでは安全ではない。でも Mersenne Twister の公式サイトには 従来存在した「線形疑似乱数(LFSRなど)プラスSHA」の 線形擬似乱数の代わりに MT を使うことは有効 なんて書かれてるんだよなぁ。。。いくら非可逆圧縮かましたところで、予測可能な数列であることに変わりはないと思うんだけどなぁ。

*1 認証がらみの場合は更にパスフレーズを含めてしまうことで、ユーザーが確かに認証を通過していることを担保する、という考え方もある。つか、むしろそうすべきなのかな。
*2 「暗号化」ではなく「符号化」である、ってのがミソ。MD5 や SHA が生成するハッシュは、必ずしも元となるテキストのみを識別するわけではなく、まったく違うテキストからでも同じハッシュ値が生成される可能性もあるため、厳密には暗号ではない。ちなみに、同じハッシュ値が生成されるテキストのことをコリジョンなどと呼んだりする。コリジョンが法則的に見つけられるようになると、これらのハッシュ関数の暗号としての強度はかなり落ちてしまうことになる。で、こんなニュースが業界で騒がれたりするわけです。つっても、こいつが弊害となるシチュエーションってのは、例えばハッシュ関数をダウンロードしたファイルの一意性 (つまり偽者のファイルだったり、ウィルスとかに感染してたりしていないこと) を証明する目的で使用する場合などであって、セッション ID (ワンタイムトークン) として使う分にはそんなに気にする必要は無かったりするわけですが。。。

Perl で CGI 用プログラムにおいて die を使う方法2006年06月21日 21時20分49秒

なんで今までこの書き方に気づかなかったんだろう。。。_| ̄|○

eval { &main_route; };
$@  and &error_message($@);
exit;

sub main_route {
    # メインの処理
}

sub error_message {
    # エラーメッセージを HTML 出力する処理
}

eval はブロック内のコードを実行する命令で、ブロック内のコードが異常終了した場合 (die で終了しようとした場合を含む) に、エラーの内容を特殊変数 $@ に書き出してくれるというもの。よーするに C++ や Java なんかで言うところの trycatch 構文みたいなこと、すなわち例外処理を行うために使用されることが多い。

$@ に書き出されるエラーの内容とは、本来であればコンソール上に出力されるか、CGI であれば HTTPD の設定で指定されたエラーログ (apache2 のデフォルトなら /var/log/apahe2/error_log とか) に書き出されるエラーメッセージそのもの。なので、例えば上記の例で main_route 関数内にて、

    open my $fin, "<$content"
        or die 'お探しのファイルを開くことができません。';

なんて書いた箇所で、ファイルを開くのに失敗してしまった場合、eval$@ に以下のような値を設定する。

お探しのファイルを開くことができません。 at /var/www/localhost/cgi-bin/sample.cgi line 24.

まともなオブジェクト指向プログラム言語であれば、例外時にどのようなオブジェクトでも飛ばすことができるし、オブジェクトの型に応じた例外処理を書き分けることもできる。Perl で同じようなことをする場合、エラーメッセージの書式を決めるとかしてあげる必要があるわけだけんども、そこまでせんでも素直に Error モジュールでも (使えるんであれば) 使ってあげたほうがよっぽどスマートなんかな。

久々にデスクトップの Gentoo 起動してみた。2006年06月22日 22時20分34秒

あいかわらず DVD 再生すると重くなるな。

しかし激しく Linux カーネル 2.6 対応した新しい Gentoo を入れ直したいのだが、これやっちゃうと 1 日仕事じゃ済まなくなるからなぁ。。。


Fri Jun 23 02:13:20 JST 2006 - 追記

emerge --sync で失敗するんですが。。。(T-T)/