PHPでパスワードの強度を調べる

(1/1)
強いパスワードをつくる」では、強いパスワードをつくる方法を説明した。では、実際につくったプログラムの強度はどのくらいだろうか――。
今回は、文字の種類や長さのほか、既存単語かどうか、パスワードの強度を調べるPHPプログラムを作ってみることにする。なお、入力したパスワードをデータベースやファイル、キャッシュに蓄えることはしないが、ネット越しにパスワードが行き来するので、万が一のことを考え、ここで検査したパスワードを本番認証には使わないようにしてほしい。

(2023年3月9日)不具合修正
(2023年2月25日)判定方法変更,リファラチェック改良
(2023年2月5日)pahooInputDataクラス導入

目次

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

PHPでパスワードの強度を調べる

サンプル・プログラムのダウンロード

圧縮ファイルの内容
passwordStrength.phpサンプル・プログラム本体
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
passwordStrength.php 更新履歴
バージョン 更新日 内容
1.2.1 2023/03/09 bug-fix
1.2.0 2023/02/25 判定方法変更,リファラチェック改良
1.1.0 2023/02/05 pahooInputDataクラス導入
1.0.0 2020/02/01 初版
pahooInputData.php 更新履歴
バージョン 更新日 内容
1.5.0 2024/01/28 exitIfExceedVersion() 追加
1.4.2 2024/01/28 exitIfLessVersion() メッセージ修正
1.4.1 2023/09/30 コメントの訂正
1.4.0 2023/09/09 $_GET, $_POST参照をfilter_input()関数に置換
1.3.0 2023/07/11 roundFloat() 追加

パスワードの強度

ここでは、パスワードの強度を下記のように定義する。数字が大きいほど強い。
  1. 数字だけ
  2. 英数6文字以下
  3. Wikipediaの見出しに存在する
  4. 記号が含まれていない
  5. 記号が含まれている

解説:文字列の長さ

文字列の長さが PASSWORD_LENGTH_MIN 未満か、または PASSWORD_LENGTH_MAX 超であるかどうかを調べるユーザー関数が [# validateLength:title= validateLength] である。
ここで、PASSWORD_LENGTH_MINを8、PASSWORD_LENGTH_MAXを64としたのは、NIST(National Institute of Standards and Technology;米国立標準技術研究所)のセキュリティ文書「NIST Special Publication 800-63B」の「5.1.1 記憶シークレット」を引用している。

 138: /**
 139:  * 指定した文字列の長さが指定した範囲内かどうかを求める.
 140:  * @return  bool TRUE:範囲内でない/FALSE:である
 141: */
 142: function validateLength($str) {
 143:     $len = strlen($str);
 144:     return (($len < PASSWORD_LENGTH_MIN|| ($len > PASSWORD_LENGTH_MAX));
 145: }

解説:数字だけ

数字だけからなる文字列かどうかを調べるユーザー関数が isNumber である。正規表現を使って判定している。

 147: /**
 148:  * 指定した文字列が数字だけかどうかを求める.
 149:  * @param   string $str 文字列
 150:  * @return  bool TRUE:数字だけである/FALSE:ではない
 151: */
 152: function isNumber($str) {
 153:     return preg_match('/^[0-9]+$/ui', $str? TRUE : FALSE;
 154: }

解説:英数字だけ

英数字だけからなる文字列かどうかを調べるユーザー関数が isAlphanumeric である。これも正規表現を使って判定している。

 156: /**
 157:  * 指定した文字列が英数字だけかどうかを求める.
 158:  * @param   string $str 文字列
 159:  * @return  bool TRUE:英数6文字以下である/FALSE:ではない
 160: */
 161: function isAlphanumeric($str) {
 162:     return preg_match('/^[A-Z|a-z|0-9]$/ui', $str? TRUE : FALSE;
 163: }

解説:Wikipediaの見出しに存在する

既存の単語かどうかを調べるのに、Wikipedia の見出しに存在するかどうかを調べることにした。このためのユーザー関数が isWikipedia である。
文字列からWikipediaの見出しURLを生成し、「PHPでリンク切れを調べる」で作ったユーザー関数 getHttpResponseCodeSize を使って存在するかどうか判定する。

 218: /**
 219:  * Wikipediaの見出しに存在する文字列かどうか
 220:  * @param   string $str 文字列
 221:  * @return  bool TRUE:存在する/FALSE:しない
 222: */
 223: function isWikipedia($str) {
 224:     $str = urlencode($str);
 225:     $url  = 'https://en.wikipedia.org/wiki/' . $str;
 226:     list($code, $size) = getHttpResponseCodeSize($url);
 227: 
 228:     return ($code == 200? TRUE : FALSE;
 229: }

解説:記号を含まない

記号を含まない文字列かどうかを調べるユーザー関数が isContainNoSymbol である。これも正規表現を使って判定している。

 231: /**
 232:  * 指定した文字列が記号を含まないかどうかを求める.
 233:  * @param   string $str 文字列
 234:  * @return  bool TRUE:記号が含まれていない/FALSE:含まれている
 235: */
 236: function isContainNoSymbol($str) {
 237:     return preg_match('/^[a-z|0-9]+$/ui', $str? TRUE : FALSE;
 238: }

解説:パスワードの強度を算出

以上のユーザー関数を順次呼び出し、パスワードの強度を算出するユーザー関数が getPasswordStrength である。

 240: /**
 241:  * パスワードの強度を算出
 242:  * @param   string $psw パスワード
 243:  * @return  int 強度
 244:  *              1:数字だけ
 245:  *              2:英数字のみ
 246:  *              3:Wikipediaの見出しに存在する
 247:  *              4:記号が含まれていない
 248:  *              5:記号が含まれている
 249: */
 250: function getPasswordStrength($psw) {
 251:     //強度と判定関数の対応表
 252:     $table = array(
 253: 0 => 'validateLength',
 254: 1 => 'isNumber',
 255: 2 => 'isAlphanumeric',
 256: 3 => 'isWikipedia',
 257: 4 => 'isContainNoSymbol'
 258: );
 259: 
 260:     //入力値(パスワード)の検査
 261:     $str = preg_replace('/[ \t]+/ui', '', $psw);    //空白を除く
 262: 
 263:     //パスワード強度判定
 264:     $res = 5;
 265:     foreach ($table as $key=>$func) {
 266:         if ($func($str)) {
 267:             $res = $key;
 268:             break;
 269:         }
 270:     }
 271:     return $res;
 272: }

参考サイト

(この項おわり)
header