▼ [萌え] Amazon のおすすめが的確すぎる件について
今度買ってこようと思っていた いいなり!あいぶれーしょん (1) をしっかりとおすすめされた。 明日の帰りにでも秋葉へ寄ってこようかな。
▼ [Perl] cryptの使い方
基本的な使い方
パスワードをハッシュして元の文字列を分からないようにしたい場合には、cryptを利用することが多い。DES が利用されるシステム (Unix系OSの多くではDESが標準) では、以下のように利用する。ここで、$salt には A-Z, a-z, 0-9, ".", "/" から無作為に2文字を抜き出して与える必要がある。(3文字目以降は無視される。) なお、この方法でcryptが生成する文字列 ($crypted_passwd) は先頭2文字がそのまま $salt となる。
$passwd ="moemoe"; # ユーザ入力を想定
$saltchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
. "abcdefghijklmnopqrstuvwxyz"
. "0123456789./";
$salt = substr($saltchars, int(rand length $saltchars), 1);
$salt .= substr($saltchars, int(rand length $saltchars), 1);
$crypted_passwd = crypt $passwd, $salt;
print "$passwd, $salt, $crypted_passwd\n";
実行結果:
moemoe, Ch, Che1un1w798gk
Cryptされたパスワード $crypted_passwd を元に入力されたパスワード $input_passwd を検証するためには、下記のように記述する。$crypted_passwdからわざわざ先頭2文字を抜き出してcryptの引数としているコードを見かけるが、後述する通りそのまま引数として渡すことで移植性が高くなる。
if(crypt($input_passwd, $crypted_passwd) eq $crypted_passwd) {
print "passwd ok\n";
} else {
print "invalid passwd\n";
}
MD5の場合
今まではDESを利用した場合について記載したが、OSによってはMD5などの要約関数が利用されている。その場合、出力される文字列はDESの場合と大幅に異なり、以下の通りとなる。
$1$salt$hashed_data
DESのみを想定してcryptされたパスワードの先頭2文字からsaltを得るように書かれたコードは、MD5を利用するシステムではそのまま利用できず、移植性が低下する。このため、移植性を考慮するのであれば、cryptの第2引数にはcryptされたデータそのものを与えることが望ましい。
FreeBSDでは米国の暗号輸出制限のため、一時期まではDESが標準で組み込まれずにMD5を利用していた。現在では、暗号輸出制限の緩和により標準でDESを組み込んでいるが、互換性の観点からMD5も利用することが出来る。(MD5形式でsaltを与えた場合にはMD5が利用される。これにより過去のパスワードデータをそのまま利用することが可能である。)
なお、MD5のみが利用できる環境 (というのも今時は珍しいが) でDESを利用したい場合には、Crypt::UnixCrypt を利用することが出来る。Pure Perl 実装であるため、コンパイラが使えないレンタルサーバなどでも利用は容易だろう。
cryptは暗号化するのか
cryptでは暗号化するわけではなく、一方向性関数 (one-way function; 逆方向の計算が非常に難しい・不可能である関数) によって得られるデータを返すだけである。したがって、厳密な意味における "暗号化" ではない。また、計算によって "復号" することも出来ない。DESを利用している場合でも、これを暗号化のために利用しているわけではなく、単に一方向性の関数として利用しているだけである。
▼ [spam] アドレス収集ボットからアドレスを隠蔽する
ウェブサイトにメールアドレスを掲載するとボット (bot = robot) に収集され、そのうちspamが大量に押し寄せるようになる。私のアドレスも10年ほど前から無防備に晒していたため、今では1日に500通ほどのspamが送信されてくる。(実際には、前述の通り中国・韓国を国ごと拒否することで緩和されているが。)
これらのbotに対抗するため以下のような方法が採られてきたが、利便性が損なわれる、実効性が低いなどの問題があり、決定打とはなっていない。
- 画像でメールアドレスを掲載
- ASCII以外の文字 (いわゆる全角) で掲載
- 実体参照で掲載
- JavaScriptで出力する
- 途中、無関係の文字列 "REMOVE-THIS-PART" 等を入れる
今回考えた方法では、無関係の文字列 "REMOVE-THIS-PART" を入れつつ、それをCSSやJavaScriptで非表示・削除することで、それらのいずれかに対応しているUAであれば通常通りに表示される。(ただし、JavaScriptに対応していないまたは無効にしてある場合には、コピー・ペーストにより "REMOVE-THIS-PART" が出現する。)
- メールアドレスを記載する場合には、以下のように "hidden" クラスに属する任意の要素を入れ、その中には適当な文字列を入れておく。その際、実際にはこの文字列を除く必要があることが分かる文字列が望ましい。
<p>sakura@<span class="hidden">REMOVE-THIS-PART.</span>example.com</p>
- スタイルシートに以下の設定を行う。
.hidden { display: none; } - 以下のJavaScriptコードを読み込ませる。(HTMLファイル中に記載、または別ファイルにして読み込ませる。
- ロード時に上記関数を呼び出す。とりあえず、bodyの開始タグに以下の設定をすれば動く。
<body onload="delete_hidden()">
function delete_hidden()
{
var elems = document.getElementsByTagName("*");
for(var i = 0; i < elems.length; i++) {
var elem = elems[i];
if(elem.className == "hidden") {
var parent = elem.parentNode;
parent.removeChild(elem);
}
}
}
この方法が十分に機能するかどうかは分からないが、JavaScriptを理解するbotでも無い限りは大丈夫… と信じたい。
