05 July 2009

PerlモジュールCrypt::DSA の/dev/randomが原因によるインストール障害

PerlモジュールCrypt::DSAのインストールを、CPANシェル上から行おうとも、コマンドラインから行おうとも、非常に長時間掛かる不具合がある。

分かりやすく説明するために、ソースコードから全て手動でインストールする方法を記載する。

Crypt::DSAのソースパッケージは、http://search.cpan.org/から最新版を取得するものとする。(下記の説明は、適宜最新版のパスに置き換えること)


root@localhost:~/working# wget http://search.cpan.org/CPAN/authors/id/B/BT/BTROTT/Crypt-DSA-0.14.tar.gz

root@localhost:~/working# tar xvf Crypt-DSA-0.14.tar.gz
root@localhost:~/working# cd Crypt-DSA-0.14

root@localhost:~/working/Crypt-DSA-0.14# perl Makefile.PL
Cannot determine perl version info from lib/Crypt/DSA.pm
*** Module::AutoInstall version 1.02
*** Checking for Perl dependencies...
[Core Features]
- Digest::SHA1 ...loaded. (2.12)
- Math::BigInt ...loaded. (1.89 >= 1.60)
[Read/write PEM-encoded files]
- Convert::PEM ...loaded. (0.07 >= 0.07)
[Read/write SSH2 keyfiles]
- Data::Buffer ...loaded. (0.04 >= 0.01)
*** Module::AutoInstall configuration finished.
Writing Makefile for Crypt::DSA

root@localhost:~/working/Crypt-DSA-0.14# make
Manifying blib/man3/Crypt::DSA::Key::SSH2.3pm
Manifying blib/man3/Crypt::DSA::Signature.3pm
Manifying blib/man3/Crypt::DSA.3pm
Manifying blib/man3/Crypt::DSA::Util.3pm
Manifying blib/man3/Crypt::DSA::KeyChain.3pm
Manifying blib/man3/Crypt::DSA::Key::PEM.3pm
Manifying blib/man3/Crypt::DSA::Key.3pm

root@localhost:~/working/Crypt-DSA-0.14# make test
~省略~
ath::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::FastCalc at /root/working/Crypt-DSA-0.14/blib/lib/Crypt/DSA/Key.pm line 6
Math::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::FastCalc at /root/working/Crypt-DSA-0.14/blib/lib/Crypt/DSA/Util.pm line 6
Name "Crypt::DSA::KeyChain::NULL" used only once: possible typo at /root/working/Crypt-DSA-0.14/blib/lib/Crypt/DSA/KeyChain.pm line 40.
← ここで恐ろしく時間が掛かる

時間が掛かるというものではなく、make test 完了まで数時間待ってもぜんぜん終わらない雰囲気。 私の予想では数日以上掛かるのでは… (笑

Googleでいろいろ検索すると、ここで時間が掛かる(フリーズしているように見える)のは、多くのサーバ管理者などでも同じ経験をしているようだ。書かれている解決策は、足りない依存パッケージを追加したとか、make testをすっ飛ばしてmake installしたとか、どれも根本的な解決ではないものばかり。

で、とりあえず足りない依存パッケージが無いか、CPANのCrypt::DSAページに記されている依存関係の各ファイルをCPANでインストールしてみる。

 ・Digest::SHA1
 ・Digest::base
 ・Math::BigInt

blib/lib/Crypt ディレクトリ以下にある DSA.pm, Key.pm, Util.pm, KeyChain.pm, Util.pm などのソースコードを眺めてみて、use宣言されている外部依存パッケージも、念のためにCPANでインストールされていることを確認する。

ここまで行っても、問題は解決しない。原因は依存関係のモジュールが無いのではなく、別のところにある

Google検索で意味深長なブログ「/dev/randomと/dev/urandom」を発見。

乱数発生の部分を grep ./* -r -e "\/dev\/random" で見つけ出す。1箇所発見された。 そこに対策を施すことにする。

blib/lib/Crypt/DSA/Util.pm

~ 省略 ~
sub makerandom {
my %param = @_;
my $size = $param{Size};
my $bytes = int($size / 8) + 1;
my $r = '';
# if ( sysopen my $fh, '/dev/random', O_RDONLY ) {
if ( sysopen my $fh, '/dev/urandom', O_RDONLY ) {← このように書き換え
my $read = 0;
~ 省略 ~

おそらく、乱数発生に/dev/randomを利用しているので、ループで何度も呼び出されるときにブロックされまくって、無限大の時間が掛かるのだろう。
安全性は下がるが擬似乱数の/dev/urandomを用いることで、人間が我慢できる範囲内の処理時間に押さえ込めるはずだ。

ということで、この変更をすることにより、make test が滞りなく進み (それでも、1分くらい掛かった)、make install まで行うことが出来た。

このモジュールの作者は、どんだけスーパーコンピューターな開発環境で実証してんだ (w