- カテゴリ: PHP
- 掲載バージョン: PHP 8.4
- 名前空間 / FQCN / コマンド:
md5 - 関連:
hash/md5_file/hash_equals/password_hash/hash_hmac - 変更履歴: 主要な仕様変更は近年なし(PHP 8系で型の厳格化により不正型で
TypeError)
要点(TL;DR)
- 任意の文字列から32桁の16進(または16バイト生)MD5ハッシュを得る
- 最低限の使い方:
$hex = md5('hello'); - よくある罠
- パスワード用途禁止(衝突耐性が弱い/総当たりに脆弱)→
password_hash()を使う $binary = trueは生バイト(NULL含む)→ そのまま表示・保存で壊れやすい- 入力はバイト列として扱われる→ 文字コード差異で結果が変わる
- パスワード用途禁止(衝突耐性が弱い/総当たりに脆弱)→
概要
md5() は入力文字列の MD5 ダイジェストを返します。結果は既定で32桁の小文字16進です。軽量な重複検出やキャッシュキー作成など非セキュア用途には使えますが、整合性検証や署名、特にパスワード保存などセキュリティが関わる用途には不適です。より安全な hash('sha256', ...)、password_hash() を選びましょう。
構文 / シグネチャ
string md5(string $string, bool $binary = false)
引数(表)
| 引数 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|
$string | string | ✓ | — | ハッシュ化する文字列(バイト列として扱う) |
$binary | bool | false | true で16バイトの生ダイジェストを返す(NULLバイト含む) |
- 戻り値:
string($binary=falseなら 32桁16進、小文字/$binary=trueなら 16バイト) - 例外/副作用:不正型(配列など)で
TypeError。$binary=trueの戻りはバイナリを含み、画面出力やJSON化で不具合になり得る。
使用例
最小例
<?php
$hash = md5('hello'); // "5d41402abc4b2a76b9719d911017c592"
echo $hash . PHP_EOL;
実務例(非セキュア用途のキャッシュキー生成)
<?php
// APIレスポンスのパラメータから安価なキーを作る(機密・改ざん検知には使わない)
$params = ['page' => 2, 'q' => 'laravel md5', 'lang' => 'ja'];
$key = 'cache:search:' . md5(json_encode($params, JSON_UNESCAPED_UNICODE));
// 値の保存
$value = ['items' => [1,2,3], 'fetched_at' => time()];
file_put_contents(sys_get_temp_dir() . "/{$key}.json", json_encode($value));
バイナリ出力の扱い
<?php
$raw = md5('hello', true); // 16バイトの生データ
$store = base64_encode($raw); // 文字列保存したい場合はエンコード
echo $store . PHP_EOL; // "XUEQKrxLKna5cZ2REBfFkg=="
多バイト文字の注意(文字コード差異で結果が変わる)
<?php
$str = 'あ'; // UTF-8 を前提
$hashUtf8 = md5($str);
$hashSjis = md5(mb_convert_encoding($str, 'SJIS', 'UTF-8'));
echo $hashUtf8 . PHP_EOL; // 8c0c3027e3cfc3d644caab3847a505b0
echo $hashSjis . PHP_EOL; // 文字コードが違えば別値
よくある落とし穴・注意
- セキュリティ用途に不適:衝突が現実的。パスワードは
password_hash()、整合性・署名はhash('sha256')以上や HMAC/公開鍵を使用。 - バイナリ戻り値:
$binary=trueはNULLバイト含むため、DBの文字列カラムやJSONに直接入れない。bin2hex()やbase64_encode()で変換。 - 改行・行末差:
"abc"と"abc\n"は別。CLIのmd5sumと比較する際は行末(LF/CRLF)差異に注意。 - 入力型:配列などを渡すと
TypeError。常に文字列へ変換してから渡す。
代替・関連APIとの比較
hash('sha256', $s):強度・汎用性はこちらが上。整合性検証や署名ベースで使うなら SHA-256 以上を選ぶ。password_hash($pass, PASSWORD_DEFAULT):パスワード専用。ソルト付与・ストレッチ込み。md5()の出番は無い。hash_equals($a, $b):ハッシュ比較でタイミング攻撃を避ける。単純な===比較より安全。md5_file($path):ファイルのMD5。軽量な重複検出には可。ただし信頼性の必要な整合性検証はhash_file('sha256', ...)を推奨。
テスト例(Pest)
<?php
it('makes 32-char lowercase hex by default', function () {
expect(md5('hello'))->toBe('5d41402abc4b2a76b9719d911017c592');
expect(strlen(md5('hello')))->toBe(32);
});
it('returns 16 bytes when binary=true', function () {
$raw = md5('hello', true);
expect(strlen($raw))->toBe(16);
});
it('depends on encoding (UTF-8 vs others)', function () {
$utf8 = md5('あ'); // UTF-8 前提
expect($utf8)->toBe('8c0c3027e3cfc3d644caab3847a505b0');
});
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
| 画面に「文字化け」や表示崩れ | $binary=true で生バイトをそのまま出力 | bin2hex($raw) や base64_encode($raw) で可視化 |
CLI の md5sum と値が合わない | 入力末尾の改行/改行コード(LF/CRLF)が異なる | 行末を揃える、rtrim($s, "\r\n") で統一 |
| 静的解析やセキュリティ診断で指摘 | MD5の脆弱性(衝突・総当たり) | 用途を見直し、password_hash() / hash('sha256') / HMAC等へ置換 |
TypeError が発生 | 配列・オブジェクトを直接渡している | 明示的に string 化((string)$value や json_encode() など) |
参考リンク
- PHP Manual — md5: https://www.php.net/md5
- PHP Manual — hash: https://www.php.net/hash
- PHP Manual — password_hash: https://www.php.net/password_hash
- PHP Manual — hash_equals: https://www.php.net/hash_equals
- IETF RFC 6151 — MD5 と HMAC-MD5 のセキュリティ考察: https://www.rfc-editor.org/rfc/rfc6151

