Wednesday, September 27, 2006

JMeter でのスレッド数、Ramp-Up 期間、ループ回数の解釈

133.217.248.30 - - [27/Sep/2006:18:10:57 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:10:57 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:10:57 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:10:57 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:10:57 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:10:57 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:07 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:07 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:07 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:07 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:07 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:07 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:17 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:17 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:17 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:17 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:17 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032
133.217.248.30 - - [27/Sep/2006:18:11:17 +0900] "GET /inv/inv?id=kajikuni&aid=20000&method=getQuote&args=4%2C3553.T%3ACVQBI%2C3789.T%3ACVQBI%2C4464.T%3ACVQBI%2C4726.T%3ACVQBI HTTP/1.1" 200 3032



スレッド数:3
Ramp-Up 期間(秒):30
ループ回数:6

にした場合のログが上のようになる。

ここから分かることは、30秒間に3つの割合でスレッドが作成される。
各々が6回テストを実行することを指定しているということだ。

結果として、10秒ごとに作成されたスレッドが6回のテストを実行する。

最初に3つのスレッドが1度に作成され、各々が30秒の間に6回のテストを実行する、
つまり、3ユーザが5秒に1回リクエストを出すことをシミュレーションしているのでは
ないということだ。

どちらもテスト総数と1秒当たりのテスト回数は同じになるが、
この違いが大きな違いになるような場合もあるだろうから気をつけること。

Saturday, September 23, 2006

暗号技術のはなし(6)

拡散と混乱を組み合わせた暗号を、「合成暗号」とよぶ。そして、拡散と混乱に使う各アプリケーションを「ラウンド関数」とよぶ。これらラウンド関数を何回も繰り返して適用することでより複雑な合成関数にしたものを「反復合成関数」とよぶ。DES は反復合成関数だ。

強固な暗号方式を使った暗号は、暗号文を統計分析してもパターンを見出すことができず解読することができない。そして潜在的な暗号化キーの数も膨大なため、総当り攻撃では現実的な時間で攻略することができない。したがって、安全ということができる。

暗号は、暗号化方式と暗号化キーの組み合わせである。そのうち秘密なのは暗号化キーだけである。方式そのものは公開しなければならない。これを「ケルクホフの原理」という。方式そのものはスパイや暗号製作者の買収などにより漏れることがあるため、暗号の安全性は方式が秘密であることに頼ってはいけない。キーが秘密であることに頼るべきである。したがって、キーは交換が容易でなくてはならないことになる。

暗号技術のはなし(5)

換字暗号では、平文の統計的なパターンが暗号文に残ってしまう。ヴィゲネーレ暗号のようなポリアルファベティックでもキーの長さは有限なわけで、まだ十分ではない。

換字に転置を組み合わせても、ある文字が別の文字に対応しているという関係は残るわけで、パターンを十分に隠蔽できるわけではない。チンパンジーがタイプしたように完全にランダムに見える暗号文を作成したいのだ。

1つの文字を複数のコンポーネントからなるものに変換したらどうか?これをするのが、「ポリビウス暗号」。

ポリビウス暗号では、文字を2桁の数字に変換する。a を 11、b を 23 とかいうように。5x5 の表をつくり、そこにアルファベットを記入していき、座標を暗号文に使う。

これだけだと、単なるモノアルファベティックな換字暗号だが、これをさらに転置する。そのとき、2桁の数字を1つ1つに分割して転置する。たとえば、e が 15 に変換されているとしたら、1 と 5 を別々に転置する。こうすると、出現頻度がもっとも高い e に対応している 15 が暗号文中にもっとも高い頻度であらわれるというような統計的パターンを隠すことができる。

現代のコンピュータを使った暗号では、文字は複数のビットで表現されるから、各ビットを転置することで同じことをより効果的に実現できる。

このようにして、平文のもつ統計的なパターンを暗号文全体にうまく分散させて隠すことができる。これを「拡散」とよぶ。これにより、暗号文を統計分析してパターンを見出し、解読するということが困難になる。

拡散とは別の概念に「混乱」がある。これは、暗号方式を既知として、それを使った暗号文から暗号化キーを推測できないようにすることだ。これは複雑な換字方式を考案することに相当する。たとえば、現代の DES 暗号では、非線形の換字暗号方式を採用することでこれを実現している。

暗号技術のはなし(4)

換字暗号方式とは別の方式として、「転字暗号方式」というのがある。これは、平文の文字の位置を入れ替えるというもの。

単純な転置、たとえば、転置表に平文を横方向に書いていき、それを縦方向に読んだものを暗号文にする、などではすぐに暗号文に残ったパターンを見抜かれてしまう。この場合なら、何文字かごとに読んでいく、というのを試していけば解読されてしまうだろう。平文に含まれているキーワードや出現頻度の高い単語に注目すると解読がしやすくなる。

暗号文に単純なパターンを残さないために、転置を1回ではなく何回も繰り返したり、転置と換字を組み合わせるなどして、パターンを発見しにくくすることができる。

たとえば、現代の暗号 DES(Data Encryption Standard)でも、転置と換字を組み合わせている。

Thursday, September 21, 2006

暗号技術のはなし(3)

平文の言語学的なパターンが暗号文にそのまま残ってしまうというモノアルファベティック暗号の欠点をなくすには、平文を暗号化するとき、1種類の文字が複数の種類の別の文字に換字されるようにすればいい。たとえば、a という文字がある場所では e に、別の場所では t に変換されるというようにすればいい。

このような換字暗号を「ポリアルファベティック暗号」という。その1つが「ヴィゲネーレ暗号」だ。

シーザー暗号では使用できる暗号化キーのうち1つだけを使って平文を暗号化していく。1つのキーで平文のすべての文字を変換するのでモノアルファベティックになってしまうのだ。ヴィゲネーレ暗号では、複数のキーを使って暗号化をおこなう。たとえば、キー番号 3, 25, 14 を使って暗号化するのであれば、平文の1番目の文字はキー番号 3 で、2番目の文字はキー番号 25 で、3番目の文字はキー番号 14 で変換する。以降、これを繰り返していく。こうすると、平文中で同じ文字でも、出現する場所によって異なる3つの文字のいずれかに変換されることになる。使用するキーの数を増やせばヴィゲネーレ暗号の強度は増す。複数のキーを1まとめにしたものを1つのキーにしているので、これはキーの長さということができる。

ヴィゲネーレ暗号のようなポリアルファベティック暗号では、平文の言語学的なパターンはモノアルファベティック暗号よりは隠蔽されている。したがって、「単純な」統計分析では破ることはできない。

暗号技術のはなし(2)

最古の暗号の1つが、シーザー暗号。これは平文を構成するアルファベットを何文字か後ろにずらして暗号文をつくる。こういうのを「換字暗号」という。

シーザー暗号の暗号化方式は、「文字をずらす」、つまり「n 番目のアルファベットを n + k 番目のアルファベットに換える」ということだ。数学的にいうと「加算」ということになる。暗号化キーは、何文字分ずらすかということであり、先の k がキーに相当する。

アルファベットの文字数は 26 なので、この方式だと暗号化キーの数は 25 種類しかなく、総当り攻撃で容易に解読できてしまう。

暗号化キーの数を増やすためには、上のようにアルファベットをシフトするだけでなく、アルファベットの並びを変更した換字を使えばいい。これだと暗号化キーの数は 25! 通り存在する。26! でないのは、a が a に換字されるというように同じ文字に換字されることがないことを保証したいためだ。

これで総当り攻撃で解読することは難しくなったが(むろんコンピュータを使えば非常に簡単だが)、十分ではない。この暗号の一番の問題点は、平文と暗号文の中の文字が1対1に対応しているということだ。これにより、文字の出現頻度などの言語学的なパターンがそのまま暗号文に残ってしまう。したがって、暗号文を統計的に分析することにより、キーが分からなくても解読できてしまうというわけだ。いうなれば、暗号方式そのもの、錠前が弱いということになる。

このような、平文と暗号文の文字が1対1に対応する換字暗号を、「モノアルファベティック暗号」とよぶ。

Wednesday, September 20, 2006

暗号技術のはなし(1)

暗号は、「暗号化方式(アルゴリズム)」と「暗号化キー」によって構成される。暗号化方式は共通でも暗号化キーを切り替えることで、同じ平文からまったく異なる暗号文に変換することができる。

暗号解析者は、キーをもっていないため、統計学的な分析などを行って暗号文を解読しようとする。これが成功すれば、同時に暗号化キーも判明することが多い(のだろう)。

このようにして解読できる暗号というのは、暗号化方式が弱いのだといえる。暗号化方式が十分に強力なら、解析者はすべての暗号化キーを試す「総当り攻撃」で解読するしかない。キーの数が膨大で、総当り攻撃で解読するのに十分な時間がかかるのであれば、その暗号は安全だといえる。

セッションID を URL に含めると、Referer ヘッダで外部に漏れてしまう件

Web アプリケーションのセッション管理に使うセッションID を Cookie ではなく、URL に埋め込んでいる場合、HTTP リクエストヘッダの Referer でそれが外部に漏れてしまう危険がある。

Web ページ A があり、そこに Web ページ B へのリンクが張られているとする。このとき、ブラウザで B へのリンクをクリックすると、ページ A の URL が Referer ヘッダでページ B の Web サーバへと送られてしまう。したがって、A の URL にセッションID が埋め込まれていて、ページ A と B の管理者が異なっている場合は、セッションID が外部に漏れてしまうということになる。

ちなみに、J2EE の HttpServletResponse#encodeURL メソッドで指定された URL にセッションID を埋め込むとき、指定された URL が自ドメインでないなら、セッションID を埋め込むことをしない。もちろん、これは、上の Referer ヘッダによるセッションID 漏洩を防ぐものではない。

リンクでないなら、Referer ヘッダが送られることはないが、ブラウザのバグで Referer が送られてしまうこともあるらしい。

以上より、セッションID を URL に埋め込むのはなるべく避けた方がいい。


http://www.studyinghttp.net/header#Referer
http://securit.gtrc.aist.go.jp/SecurIT/advisory/webmail-1/
http://securit.gtrc.aist.go.jp/SecurIT/advisory/referer-2/

Friday, September 08, 2006

JMeter のリモート実行で java.rmi.ConnectException: Connection refused to host: 127.0.0.1 が発生する場合

JMeter は Jakarta プロジェクトで開発が進められているパフォーマンス計測用のツール。

クライアントマシンで実行することもできるが、多くのスレッドを起動したり、大量のリクエストを飛ばすので、テスト対象のサーバが限界に達する前にクライアントマシンやネットワークが過負荷になったり、会社などで実行するとネットワークを管理している部署から苦情が来たりする。

こういう場合、JMeter のリモート実行機能を使えばいい。テスト計画を手元の PC 上の JMeter で作成し、それをリモートのおそらく PC よりも処理能力の高いサーバ上にある JMeter で実行する。リモートの JMeter は手元の PC の JMeter で管理する。

このために、JMeter を実行するリモートサーバで次のようにする。


$ export CLASSPATH=$CLASSPATH:$JMETER_HOME/lib/ext/ApacheJMeter_core.jar:$JMETER_HOME/lib/jorphan.jar:$JMETER_HOME/lib/logkit-1.0.1.jar

$ rmiregistry

$ jmeter -n -s


リモート実行では、RMI を使う。rmiregistry は、ネットワークオブジェクトの位置を登録したり問い合わせたりするサービス。これは、JDK に付属しているツールで、デフォルトで 1099 ポートをオープンする。-n で非 GUI モード、-s でサーバモードで JMeter を起動する。現在、非 GUI モードでも X-Window 関係のライブラリは必要となっている。

クライアント PC では、jmeter.properties ファイルの remote_hosts でリモートサーバを指定してから、JMeter を起動する。

そのようにしてから、JMeter のリモート実行を開始したのだが、うまくいかなかった。PC の jmeter.log を確認してみると、


java.rmi.ConnectException: Connection refused to host: 127.0.0.1


が発生していた。これは、rmiregistry がネットワークオブジェクトのメソッドコール用のアドレスとして自分のローカルアドレス 127.0.0.1 をクライアント PC に通知しているために起こっていると考えられる。リモートサーバの /etc/hosts ファイルを調べてみると、


127.0.0.1 localhost mail


というエントリがあった。mail が DNS にも登録されている名前なのだが、これをこのエントリから削除すると、さっきの例外は発生しなくなった。rmiregistry がネットワークオブジェクトのメソッドコール用として使うポートは 1099 ではなく、ランダムに選んでいるようなので、もし、リモートサーバで Firewall を実行しているなら、クライアント PC からの接続に関してはすべてのポートを許可するようにしておかなくてはならない。

実は、このようにしてもリモート実行はうまくいかなかった。jmeter.log を見ると、リモートサーバがソケットをクローズしてしまうらしい。仕方ないので、リモートサーバにテスト計画(.jmx ファイル)をコピーし、そこで直接 JMeter を実行して、テスト結果のログ(.jtl ファイル)をクライアント PC の JMeter の Listener に指定して表示させた。


$ jmeter -n -t TestPlan.jmx -l Log.jtl


-t オプションでテスト計画のファイルを指定し、-l オプションでログファイルを指定する。このログファイルをクライアント PC の JMeter のリスナーで読み込んで表示する。

ただ、テスト計画ファイルに日本語が含まれていると、ログファイルが文字化けしてしまう。これが原因となってリスナーで読み込むときにエラーになるときもあるので、テスト計画ファイルを作成するとき、テスト計画名などはすべて英語にし、メニューバーのオプションで言語も英語にした方がいい。