プロが教えるわが家の防犯対策術!

パスワードなどを暗号化する際に使用するcrypt関数ですが、最適なsaltの求め方というのはあるのでしょうか。
最も多いと思われるのは、
srand();
@salts = ("A" .. "Z", "a" .. "z", "0" .. "9", ".", "/");
$salt = $salts[int(rand(64))] . $salts[int(rand(64))];
という、普通に乱数を使ったものですが、
結構有名なCGI RESCUEでは、
http://www.rescue.ne.jp/cgi/private2/crypt.cgi
ランダムな$keisuと時間を基に、かなり面倒(?)な方法を使っています。
これが何をやっているのか、いまいちわかりません。また、なぜこのような方法にするのか、ご教授のほどお願いいたします。

A 回答 (5件)

確かに一見して奇妙ですね。


どう考えても結局randを基にしているのだから、繰り返す意味は無いですよね。
他の方もおっしゃっているように、salt2文字を求めるコード自体を複雑にする効果は特にないと、私も思います(むしろ素直にrandを使ったほうが再現性は低い気がします)。

ご存知かと思いますが、cryptによって生成された暗号化文字の先頭2文字は使われたsaltになります(DESの場合)。なので、実際は暗号化された文字を見ればsaltは判明し、隠そうとする意味はありません。
saltは元の文字列から暗号化する際に56bitの数値を使って演算に加味するというだけの目的ですから、いつも同じものを使うことを避けさえすれば、salt自体を隠す意味はあまりないと思います(厳密には隠せない)。

で、このコードの理由については、あくまでも確信のない推測ですが、成り行きでこうなったとか、「特に意味がない」ということじゃないでしょうか。
良く見てみると、ループが、8文字のsaltに対応させることを容易にさせるためにも見え、MD5のことを考慮してか、あるいはMD5バージョンがあって書き換えたが処理は残っているとか。
そしてまた、timeとの%を取るというのはrandを使わずに乱数を求めるようなケースで昔はたびたび使われた手法でもあり、もともとそのような処理だったのが、randによる方法に改良した、しかしこれもやはり中途半端に残ってしまっている、というようなことではないでしょうか。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
言われてみれば確かにシャッフル?を8回繰り返してますね。これが8文字のsaltに関係する(してた)可能性はありそうですね。
if ($pwd =~ /^\$1\$/)というところは、まさしくMD5用でしょうし。
シャッフルはrandを使っておきながら、そこから1文字取る方法だけ時間などを使っていて、無意味というか意味が解らないですが、、、確かに書き換えを繰り返していくうちにこうなってしまった、と考えると納得できる気がします。

おっしゃるように、どうも特に意味がないというのが正解な気がしました。
その証拠?に、このサイトの最近のプログラムだと、こんな面倒なことしてないんですよね、、先ほど気づきました。そしてこれは古そうです。

本題の疑問だった、saltは単純にrandで良いということが解っただけでも良かったです。

お礼日時:2006/09/23 13:23

古いバージョンのperlで動かす事を想定して、乱雑さを増すために、わざと何度もrandをコールする方法をとっているのでは。


最近のperlならあえてsrandを呼ばなくてもすむはずなので。

ソルトの出現確率が一律であるのが最適なので、内部にカウンタをもって0から4095まで順番に払い出すのがベストだったりして。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
なるほどrandの信頼性を補足するようなものですかね、、、。
いろいろなサンプルや信頼できそうな配布プログラムなども見てみましたが、結局どうやら単にrandでよさそうだという気がしてきています。
いまのところ古いバージョンを想定する必要もないので。

お礼日時:2006/09/23 13:13

Salt文字列を固定ではなく、ランダムにして生成しているのは、Salt文字列と暗号化した文字列の表から、元の文字列を解読するのを難しくする為だと思います。


予め、いくつかのSalt文字列からの表があれば、同じSalt文字列を使用している暗号文字列を解読するのが容易になります。

パスワードをいくつも保存しているファイルがあれば、そのなかのどれかはSalt文字列が同じであるかもしれません。
また、同じSalt文字列が何度も現れていれば、その中で一番多いSalt文字列からその表を作れば、それだけ多くのパスワードが解読できます。

Salt文字列の再現性が低いほうがセキュリティが高いということになります。

なので、CGI RESCUEさんが、複雑な方法で、Salt文字列を生成しているのは、単純な方法でSalt文字列を生成するよりも、再現性が低いと、作成者が考えたからではないでしょうか。
実際に低いのかどうかは別ですが…(変わらないような気もします)

参考URL:http://www.nurs.or.jp/~ogochan/linux/crypt.html
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
saltを再現性の低いものにするためランダムに、というのは理解しております。

>実際に低いのかどうかは別ですが…(変わらないような気もします)
そうなんですよ、、、これって、ランダムの文字列を作る方法として、「randを使う方法」と「時間などから演算する方法」とが、混ざっているようなんですよね。
いろいろ他のサンプルもかなり見てみましたが、どうやら単純にrandでよさそう、という気がしてきています。このプログラムだけの、ちょっと不思議な特徴、というところでしょうか。

お礼日時:2006/09/23 13:09

>それでもやはり解析しにくいようにする必要があるのでしょうか。


 サンプルとしての意味もありますからね。

>それほど難解or無意味な処理でもないように思えます
 削除しても問題のないロジックが入っているわけではないですから。
 複雑なロジックを実装するために必要な処理が入っているわけですから、単純な暗号の場合には、プログラムを複雑化するのも限界があります。

>これでは危険ということですか?
 ソースコードを第三者に読まれてしまうケースでは、ロジックを複雑化することは「プログラマーとしてのセキュリティ意識を示す」ことに最大の意義があります。
 実際には、やる気のあるハッカーにかかれば解析そのものは簡単なのですから、セキュリティの危険度は同じといえると思います。
 でも、ガキのイタズラすら防げないという意味では、単純なソースコードは危険といえるでしょう。

この回答への補足

ご回答ありがとうございます。
何度もすみません。
どうもやはり私には、暗号化のロジックではなくsaltのロジックを複雑化する効果や意味が良く解らないのが正直なところです。
サンプルであるなら、むしろなおさら(他のサンプルのほとんどがそうであるように)理解しやすいように書くべきな気がするのと、逆にrandと書いたほうが解析できないと思うのですが…。
どうも、このプログラムだけの問題な気がしてきています。

しかし意義などの件は大変参考になりました。ありがとうございます。

補足日時:2006/09/23 12:59
    • good
    • 0

>これが何をやっているのか、いまいちわかりません


 そう思わせるためにわざと面倒な方法を使います。そのような場合、システム的には必要のないロジックがわんさか入ってたりします。
 解析しやすかったら暗号の意味がないですから。
    • good
    • 0
この回答へのお礼

早速のご回答ありがとうございます。
なるほど、解析しにくいようにでしたか。
ただ、これは暗号化そのものではなくて、たった2文字のsaltを求めるだけですが、それでもやはり解析しにくいようにする必要があるのでしょうか。
また、カムフラージュ(?)的なことが目的にしては、それほど難解or無意味な処理でもないように思えます(最終的には2つの乱数を作っているだけ?)。
他の多くのスクリプトでは、質問文に書いたような数行の処理で済ませていますし…、これでは危険ということですか?
重ねてすみませんが、よろしくお願いいたします。

お礼日時:2006/09/22 11:26

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!