はじめに
・PHPで、セキュリティに関心がある方
・ハッシュ、ハッシュ関数が分からない方
ハッシュとは
ハッシュとはアルゴリズムに基づき、**読解不可能な文字列などに置換する仕組み
**のことです。
※パスワードなどの機密情報を扱う時になどに使用します。
代表的なハッシュ関数
PHPには標準で、**文字列からハッシュ値を計算し、生成する関数
**が存在します。
※以下が代表的な、ハッシュ関数です。
|ハッシュ関数|詳細|
|:---:|:|
|hash|指定したアルゴリズムで、ハッシュ値を生成する ※バージョン 5.1.2以降|
|md5|MD5方式で、16進数・32文字のハッシュ値を生成する|
|sha1|SHA-1方式で、16進数・40文字のハッシュ値を生成する|
|password_hash|機密性の高い文字列のハッシュ値を生成する ※バージョン 5.5以降|
hash
<?php
$str = 'hoge';
var_dump(hash("sha256", $str));
?>
string(64) "ecb666d778725ec97307044d642bf4d160aabb76f56c0069c71ea25b1e926825"
md5
<?php
$str = 'hoge';
var_dump(md5($str));
?>
string(32) "a577f0035386e7d04551e867b3d9f024"
sha1
<?php
$str = 'hoge';
var_dump(sha1($str));
?>
string(40) "31f30ddbcb1bf8446576f0e64aa4c88a9f055e3c"
password_hash
<?php
// ハッシュ値を計算する前の文字列
$str = "hoge";
// ハッシュ値を計算
password_hash($str, PASSWORD_DEFAULT);
?>
string(60) "$2y$10$zgsW6rm.9wcBnkSw2/Jp3OiJSDy5gsEUAM6fum4zva7/5jauNVixK"
おまけプログラム
IDとパスワードを入力し、DBに保存するプログラムを作成しました。なお、パスワードは**password_hash
**を使用し、ハッシュ化しています。
※今回使用するDB情報
|ユーザー名|DB名|カラム名情報①|カラム名情報②|
|:---:|:|:---:|:---:|:---:|
|id_pass_user|hashdb|id_data varchar(100)|pass_data varchar(100)|
新規で作成した、ユーザーにはパーミッション(権限)がないので、以下のコマンドで付与します。今回の場合は、**id_pass_user
**にDBレベル(hashdb)での付与になります。
mysql> grant all on hashdb.*to id_pass_user@localhost;
※入力する、IDとパスワード
|ID|パスワード|
|:---:|:|:---:|
|hogeID|hogePASS|
コード一覧
<?php
// ID,パスワードと、DBのバリデーションの補助を実装したクラス
class DataVaildataion {
//ID,パスワードと、DBのバリデーションに必要なデータをカプセル化
private $hash_pass = null;
private $success_message = null;
private $error_message = null;
private $clean = array();
# ゲッターは今回必要ないので、コメントアウト
/*public function getHashPass() {
return $this->hash_pass;
}
public function getSuccessMessage() {
return $this->success_message;
}
public function getErrorMessage() {
return $this->error_message;
}
public function getClean() {
return $this->clean;
}*/
// セッターで、ID,パスワードのバリデーションの補助
public function setHashPass($hash_pass) {
return $this->hash_pass = $hash_pass;
}
public function setSuccessMessage($success_message) {
return $this->success_message = $success_message;
}
public function setErrorMessage($error_message) {
return $this->error_message = $error_message;
}
public function setClean($clean) {
return $this->clean = $clean;
}
}
?>
<?php
// 必要なプロパティのあるクラスファイルの呼び出しと、インスタスの生成
require_once('data_vaildataion.php');
require_once('from.php');
$data = new DataVaildataion();
// データベースの接続情報を定数で実装
define( 'DB_HOST', '127.0.0.1'); # phpadminの場合は、localhost
define( 'DB_USER', 'id_data_user');
define( 'DB_PASS', '各自のパスワード');
define( 'DB_NAME', 'hashdb');
// Dataクラスのセッターを使用し、ID,パスワードのバリデーションを実装
if(!empty($_POST['btn_submit'])) {
if(empty($_POST['id_data']) || empty($_POST['pass_data'])) {
echo $data->setErrorMessage('IDまたは、パスワードが未入力です。').PHP_EOL;
exit();
}else {
// Dataクラスのセッターを使用し、IDのサニタイズの実装 (シングルクフォートと、ダブルクフォートをHTMLに変換しない)
$data->setClean($clean['id_data'] = htmlspecialchars( $_POST['id_data'], ENT_QUOTES));
// 上記と同じく、パスワードのサニタイズの実装
$data->setClean($clean['pass_data'] = htmlspecialchars($_POST['pass_data'], ENT_QUOTES));
// セキリュティを考慮し、password_hashを採用(同じハッシュを生成しない。DBとの比較の際は、password_verifyを採用)
$data->setHashPass($hash_pass['hash_pass'] = password_hash($clean['pass_data'], PASSWORD_DEFAULT));
}
// Dataクラスのセッターを使用し、DBのバリデーションを実装後、DBに保存
if(empty($data->setErrorMessage($error_message)) ) {
$mysqli = new mysqli( DB_HOST, DB_USER, DB_PASS, DB_NAME);
if($mysqli->connect_errno ) {
echo $data->setErrorMessage('エラー番号 '.$mysqli->connect_errno).PHP_EOL;
exit();
}else{
$sql = "INSERT INTO hash (id_data, pass_data) VALUES ( '$data->setClean($clean[id_data])', '$data->setClean($hash_pass[hash_pass])')";
}
$res = $mysqli->query($sql);
if($res) {
echo $data->setSuccessMessage('登録が完了しました。');
}else{
echo $data->setErrorMessage('登録に失敗しました。');
}
$mysqli->close();
}
}
?>
<?php
require_once('data_vaildataion.php');
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ハッシュ化しよう</title>
</head>
<body>
<h1>新規登録画面</h1>
<div class="input_area">
<form action="db.php" method="post">
<dl class="id">
<dt>ID</dt>
<dd><input type="text" name="id_data"></dd>
</dl>
<dl class="pass">
<dt>PASS</dt>
<dd><input type="text" name="pass_data"></dd>
</dl>
<input type="submit" name="btn_submit" value="新規登録">
</form>
</div>
</body>
</html>
+----+---------+----------------------------------------------------------------+
| id | id_data | pass_data |
+----+---------+----------------------------------------------------------------+
| 1 | (hogeID) | ($2y$10$0V2iu9qPDLJ/LOo629jT2OSNWlEHqUzADek23k.Ns.swWZiT3GRxu) |
+----+---------+----------------------------------------------------------------+
※上記のコードで、IDとハッシュ化されたパスワードがDBに保存できます。
参考サイト
・文字列からハッシュ値を取得する