PHPにおけるパスワードの暗号化について その2

色々考えたけど、結局良く分からなかった。

ストレッチングの重要性はともかくとして、コストと安全性のトレードオフについては目的に応じて自分の勘で判断するしか無いという微妙な結論に…(・_・;)
crypt()のコスト=ストレッチングであるか否かはわからんちんヽ(・_・)ノ
# ソースを読むべき。いつか、そのうち、きっと

QA@ITと言うところで質問してみたところ、親切にも二人も回答して下さった方がいた。

PHPでのパスワードの暗号化について
http://qa.atmarkit.co.jp/q/2975?_nid=1255

# 一人目の回答者さんには今頃気がついて大変失礼なことをしてしまいました

回答として書いてくださった一人目の回答者さんからは、ストレッチングは単なる時間稼ぎじゃないんだよということをソース付きでお教え頂きました。
Key stretching
http://en.wikipedia.org/wiki/Key_stretching

しかし、この辺の事情を加味したとして、将来的にアルゴリズム換えますといった保守を考えると、スライドのように自作するのはやっぱりなんとなく嫌。
# 回答者さんのおっしゃっている通り、文字通りのサンプルであるなら言わずもがな

二人目の回答者さんはコメントでご回答下さいました。曰く、password_hash()password_verify()を使うのがよろしいのではと。これらの関数はPHP 5.5からの実装になりますが、互換ライブラリが提供されており、導入出来れば同じように使うことが出来そうです。

ライブラリの導入はどうやるんだ?(・_・)
と思っていたら何のことはない普通にPHPのソースだったので、私の使っているさくらサーバーでも、自分のコードと一緒にサーバに置いてあげれば使えそう。

カテゴリー: プログラミング | タグ: , | コメントする

PHPにおけるパスワードの扱いについて

Webアプリケーションでログインの機能をつける時、大抵ユーザーIDとパスワードを使う。アプリケーション内でのユーザーのなりすましを防ぐために、パスワードは丁重に扱わなくてはならない。

と、言うところまでは言葉では分かったが、実際どうすればいいのかがいまいち分からなかった。とりあえず、平文のままパスワードをデータベースの中に放り込むのは論外として、じゃあ暗号化だなということで調べ始めた。

すると、手軽な方法でPHPのネイティブな関数にcrypt()というものがあることが分かった。

PHP: crypt – Manual
http://www.php.net/manual/ja/function.crypt.php

第1引数で指定した文字列(パスワード)を第2引数で指定されたsalt(これで使用するハッシュ関数一緒に指定する)でハッシュした文字列を得るということでこれを「暗号化されたパスワード」としてデータベースに保存すればOKと言う事になる。

PHP: パスワードのハッシュ – Manual
http://www.php.net/manual/ja/faq.passwords.php

関連のこのページを読んで見るとハッシュアルゴリズムにはBlowfishが良いだろうというようなことが書いてあったので、それを使えばいいのかなとなんとなく理解した。つまるところ他のMD5やSHA1よりましであるようだ程度の認識だ。この関数で使用出来る用意されたアルゴリズムはBlowfish以上のものだとSHA256とSHA512で選択肢はそんなにない。利用できるかは設定によるようだが…とりあえず、あとは危険でないsaltの指定方法を探したのだがここでハマった。

結論としてはsaltについては十分に長くてそれなりに複雑であればなんでもいい。アカウントごとにsaltを用意してあげる必要がある。そしてsaltをハッシュとともに保存しておく。ということは分かった(時間がかかったが)。

問題はそれを調べる過程で本当にcrypt()を使っていいのかという疑問を持ってしまったことだ。

Webアプリでパスワード保護はどこまでやればいいか
http://www.slideshare.net/ockeghem/how-to-guard-your-password

セキュリティ関連で著名な方らしい、徳丸さんという方のスライドである。この中で「ストレッチング」と言うハッシュの計算を相当数繰り返す方法をとるべきであると主張されている。例のコードではhash()と言う関数でSHA256が使われ、それが1,000回繰り返されていた。

crypt()のSHA256の説明には「’rounds=<N>$’ で始まる場合は、数値 N がハッシュループの実行回数を表します。」と書いてあったのでこれがストレッチングに相当するのか?

http://www.akkadia.org/drepper/SHA-crypt.txt

このへん見るとそうっぽいんだけどそもそもこれ、UNIXの実装の話だし。…そうだとするとわざわざ自作する必要性がよくわからなくなる。

カテゴリー: プログラミング | タグ: , | コメントする

Windows7でタスクスケジューラを使用する

Windowsで起動時や一定時間ごとに作業を行いたい時は「タスクスケジューラ」を使用することで自動化出来る場合がある。

詳細は
タスク・スケジューラの基本的な使い方(Windows 7/8編)
http://www.atmarkit.co.jp/ait/articles/1305/31/news049.html

タスク・スケジューラで数分おきにプログラムを繰り返し実行する
http://www.atmarkit.co.jp/fwin2k/win2ktips/1332reptsk/reptsk.html
を参照。

タスクスケジューラの画面
task_scheduler01

今回設定した項目
task_scheduler02
task_scheduler03

一旦設定した後にプロパティを開きトリガーを詳細設定。試しに5分毎に実行する。
task_scheduler04

実行結果


D:\Cani\php\time_log>time
現在の時刻: 1:32:11.17
新しい時刻を入力してください:

D:\Cani\php\time_log>dir
ドライブ D のボリューム ラベルは ボリューム です
ボリューム シリアル番号は E0DB-6441 です

D:\Cani\php\time_log のディレクトリ

2013/06/03 01:35 <DIR> .
2013/06/03 01:35 <DIR> ..
2013/06/03 01:35 21 time.log
2013/06/03 01:05 758 time_log.php
2013/06/03 01:03 675 time_log.php~
3 個のファイル 1,454 バイト
2 個のディレクトリ 1,890,682,781,696 バイトの空き領域

D:\Cani\php\time_log>type time.log
2013-06-03 01:35:00

D:\Cani\php\time_log>time
現在の時刻: 1:46:51.59
新しい時刻を入力してください:

D:\Cani\php\time_log>type time.log
2013-06-03 01:35:00
2013-06-03 01:40:00
2013-06-03 01:45:00

D:\Cani\php\time_log>

5分おきにPHPのスクリプトが実行されていることがわかる。
実行するたびにコマンドプロンプトが開くのか画面がちらついた。

 

追記

CLI と CGI
http://php.net/manual/ja/migration5.cli-cgi.php

によると”php-win.exe“を利用すればコンソールは表示されないようだ。

カテゴリー: Windows | タグ: | コメントする

PHPでファイルに書き出す

カレントディレクトリの”time.log“と言うファイルに現在時刻を追記する。”time.log“ファイルが存在しない場合はファイルを作成し、現在時刻を書き出す。

<?php
$filename = 'time.log';
// デフォルトタイムゾーンを指定
date_default_timezone_set('Asia/Tokyo');

try {
  // time.logが存在するか
  if (file_exists($filename)) {
    $fp = fopen($filename, 'ab'); // 追記モードでオープン
  } else {
    $fp = fopen($filename, 'wb'); // 新規作成してオープン
  }
  if ($fp != FALSE) {
    // オープンに成功していたら
    fwrite($fp, date("Y-m-d H:i:s")."\r\n"); // 現在日時を書き出し
    fclose($fp);                             // ファイルを閉じる
  }
} catch (Exception $e) {
  echo 'エラー:', $e->getMessage(), "\n";
}
?>

以下、実行結果


D:\Cani\php\time_log>dir
ドライブ D のボリューム ラベルは ボリューム です
ボリューム シリアル番号は E0DB-6441 です

D:\Cani\php\time_log のディレクトリ

2013/06/03 00:46 <DIR> .
2013/06/03 00:46 <DIR> ..
2013/06/03 00:39 654 time_log.php
1 個のファイル 654 バイト
2 個のディレクトリ 1,890,683,060,224 バイトの空き領域

D:\Cani\php\time_log>php time_log.php

D:\Cani\php\time_log>dir time.log
ドライブ D のボリューム ラベルは ボリューム です
ボリューム シリアル番号は E0DB-6441 です

D:\Cani\php\time_log のディレクトリ

2013/06/03 00:46 21 time.log
1 個のファイル 21 バイト
0 個のディレクトリ 1,890,683,060,224 バイトの空き領域

D:\Cani\php\time_log>type time.log
2013-06-03 00:46:24

D:\Cani\php\time_log>php time_log.php

D:\Cani\php\time_log>type time.log
2013-06-03 00:46:24
2013-06-03 00:46:52

D:\Cani\php\time_log>
カテゴリー: プログラミング | タグ: , | コメントする

PHPでファイルが存在するか調べる

カレントディレクトリに”test.txt“と言うファイルが存在するか調べる。
存在すれば「test.txt is exists.」、存在しなければ「test.txt is not exists.」と表示する。

<?php
$filename = "test.txt";
if (file_exists($filename)) {
  echo $filename . " is exists.";
} else {
  echo $filename . " is not exists.";
}
?>

以下、実行結果。


D:\Cani\php>dir
ドライブ D のボリューム ラベルは ボリューム です
ボリューム シリアル番号は E0DB-6441 です

D:\Cani\php のディレクトリ

2013/06/02 01:20 <DIR> .
2013/06/02 01:20 <DIR> ..
2013/06/02 00:48 156 fileexist.php
1 個のファイル 156 バイト
2 個のディレクトリ 1,890,692,272,128 バイトの空き領域

D:\Cani\php>php fileexist.php
test.txt is not exists.

D:\Cani\php>echo > test.txt

D:\Cani\php>dir test.txt
ドライブ D のボリューム ラベルは ボリューム です
ボリューム シリアル番号は E0DB-6441 です

D:\Cani\php のディレクトリ

2013/06/02 01:20 21 test.txt
1 個のファイル 21 バイト
0 個のディレクトリ 1,890,692,272,128 バイトの空き領域

D:\Cani\php>php fileexist.php
test.txt is exists.

D:\Cani\php>
カテゴリー: プログラミング | タグ: , | コメントする

投稿テスト

投稿テスト。

カテゴリー: 未分類 | コメントする