PHPでパスワードを生成

(1/1)
これから、短くても実用的なプログラムの作り方を通じて、PHP プログラミングの初歩を紹介していく。
まず最初に、パスワードを生成するプログラムをつくってみることにする。

サンプル・プログラム

まずは PHP のソースプログラムをダウンロードしてほしい。
解凍できたら、password.php というファイル名で Apache の仮想ディレクトリが通っているディレクトリにセーブすること。
なお、画面に表示している行番号は説明の便宜上のものであり、ソースプログラムには含まれていない。

0001: <?php
0002: /**
0003:  * パスワードを生成する
0004:  * @copyright (c)studio pahoo
0005:  * @author     パパぱふぅ
0006:  * @version     1.0  2004/09/26
0007: */
0008: /**
0009:  * マイクロ秒により乱数器に種まき
0010: */
0011: function make_seed() {
0012:     list($usec$sec) = explode(' ', microtime());
0013:     mt_srand((float) $sec + ((float) $usec * 100000));
0014: }
0015: 
0016: /**
0017:  * パスワードを生成する
0018:  * @param int        $len パスワードの長さ
0019:  * @param string    $str パスワードに使う文字の並び
0020:  * @return string    パスワード
0021: */
0022: function make_password($len$str) {
0023:     $l = strlen($str) - 1;
0024: 
0025:     $psw = "";
0026:     for ($i = 0; $i < $len$i++) {
0027:         $n = (int)mt_rand(0, $l);
0028:         $psw = $psw . substr($str$n1);            //1文字追加
0029:     }
0030:     return $psw;
0031: }
0032: 
0033: //メインプログラム ========================================================
0034: print make_password(10, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
0035: ?>

サンプル・プログラムの実行方法

ブラウザから http://localhost/***/password.php (*** はセーブした仮想ディレクトリ名)と入力すると、数字+英大文字から成る 10 桁のパスワードが表示される。
これが PHP プログラムである。

PHPプログラムの始まりと終わり

PHP プログラムは <?php ... ?> の間に記述する。また、ファイルの拡張子は原則として .php を用いる。
他の記述法もあるが、基本は <?php ... ?> である。

コメント

ソース・プログラムには、あとで何を書いたか分からなくならないように、できるだけコメントを記しておこう。
PHP は C, C++と同様のコメント記法を採用している。
すなわち、
  • // から行末まではコメント(1行コメント)
  • /* ... */ の間はコメント(複数行コメント)
の 2 つである。password.php では、複数行コメントのみ用いている。意図的に@を使っているのだが、これについては次回述べることにする。

ユーザー定義関数

PHP は、C と同じように、ユーザーが関数を定義することができる。
ユーザー定義関数は、
function 関数名(引き数)  {  処理内容  }


のように記述する。password.php の 11~14行目などがそうである。

関数名は、アンダーバーまたはアルファベットで始まる文字列で、2 文字目以降は数字も混在してよい。英小文字・大文字は区別される。
引き数には、この関数内だけに通用する(スコープ)変数を指定する。
PHP の変数は必ず $ で始まる。次に、アンダーバーまたはアルファベットが続き、その次からは数字も混在してよい。英小文字・大文字は区別される。
引き数を指定しない場合は、C のような void 指定は不要。

PHP には変数の「型」の概念がないので、引き数や関数の型を指定する必要はない。ただし、コメントには型を明記した方が親切だと思う。C または Java の型名で記述すればよいだろう。

組み込み関数

PHP は、非常に多くの組み込み関数を持っている。
画面表示や DB アクセスに始まって、数字に 3 桁区切りのカンマを付けたり、文字列から HTML の外したりと、考えられるルーチンワークのほとんどは組み込み関数で用意されている。この点が PHP の大きな魅力である。
他方、これら組み込み関数は PHP のバージョンによって変化しており、参考書籍の情報は古いことが多い。そこで、最新のオンライン・マニュアル(日本語)を参考にした方がよい。

password.php では、まず、12行目の関数  microtime  が組み込み関数である。
これは、文字列 "msec sec" を返す。sec は現在時刻を Unix epoch (1970 年 1 月 1 日 00:00:00)からの通算秒としたもので、msec は マイクロ秒の部分である。

関数  explode  は、指定した文字で文字列を分解し、各々を配列に入れて戻す組み込み関数だ。12行目では空白を区切り文字にして分解している。

関数  list  は PHP ならではのユニークな組み込み関数で、関数  explode  のように戻り値が配列である場合、一気に複数の独立した変数に代入することができる。ここでは、変数 $usec にミリ秒が、変数 $sec に秒が代入される。
関数  mt-srand  は乱数の種(シード)を設定する関数である。乱数の乱れを向上させるため、後述の関数  mt-rand  を使う前に必ず呼び出すのが定石である。

演算子

四則演算を行うのは、+ - * / で、他の言語と同じである。優先順位も同様。代入を行う = はとくに代入演算子と呼ばれる。
文字列を結合する演算子は . (ピリオド)である。

PHP はデータ型の概念を持たないので、演算子によって結果が異なることがある。
たとえば、$a = 1, $b = 2 のとき、$a + $b の結果は 2 であるが、 $a . $b の結果は 11 となる。数値として加算が行われたか、文字列として接続が行われたかの違いである。
そこで、計算結果を明らかにするために、明示的に型を指定することがある。これが「型指定演算子」で、int(整数)、float(単精度浮動小数)、double(倍精度浮動小数)、string(文字列)、array(配列)、object(オブジェクト)がある。

その他にも様々な演算子がある。

演算子や関数を用いた「式」は PHP プログラムの最小構成単位である。詳細はオンラインマニュアルを参照のこと。

文字列操作

22~31行目が、パスワードを生成するユーザー定義関数 make_password だ。引き数に、生成するパスワードの長さ $len と、パスワードに使用する文字種 $str を指定する。
実際に、この関数を呼び出すのは 34行目で、10 桁、英数大文字から成るパスワードを生成させている。

23行目の関数  strlen  は、引き数に与えられた文字列の長さを返す。ここでは、パスワードに使用する文字種の数から 1 を減じた値を変数 $l に代入している。

26行目の for 文は繰り返し処理を行う。
一般的に、for (式 1; 式 2; 式 3) 文 の形で用いられ、初期値が (式 1) で、(式 2) が真である間、(文) を実行し、(式 3) を実行する。
26行目では、変数 $i が 0 から始まり、$i$l 未満である間、27~28行目を実行、$i を 1 だけ増やす($i++)処理を行う。

27行目では、0 以上 $l 以下の乱数を発生させ、$n に代入する。
28行目で、関数  substr  を使っているが、この関数は与えられた文字列から部分文字列を取り出すものである。ここでは、文字列 $str$n 番目から 1 文字だけ取り出して、変数 $ch に代入している。これは、すなわち、パスワードに使用する文字種から任意の文字を 1 文字だけ取り出すことを意味する。

そして、変数 $ch をパスワード文字列 $psw の後に結合させるという処理を、指定した長さ(回数)になるまで for 文によって繰り返し実行している。

プログラムの評価

こうしてできたプログラム password.php を実行し、パスワードの解き明かされにくさを評価するフリーソフト「Password Evaluation Soft」を実行したところ、ほぼ 100%の割合で合格した。

ただし、ここで生成されたパスワードは、ネットワーク上を平文で流れるので、盗聴は可能である。それを防ぎたいのであれば、SSL などの暗号化を別途用意する必要がある。
(この項おわり)
header