Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】hash_final()関数の使い方

hash_final関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

hash_final関数は、PHPのhash拡張モジュールに属し、進行中のハッシュ計算を完了させ、最終的なハッシュ値(ダイジェスト)を取得するために実行する関数です。

ハッシュ計算は、データの整合性検証やパスワードの安全な保存など、セキュリティ関連の用途で利用される、入力データから固定長の短い文字列(ハッシュ値)を生成する一方向の処理です。このhash_final関数は、そのハッシュ計算プロセスの最後のステップを担います。

一般的な利用方法としては、まずhash_init()関数で特定のハッシュアルゴリズムを使用して計算コンテキストを初期化します。次に、hash_update()関数を繰り返し呼び出すことで、計算対象となるデータを順次そのコンテキストへ追加していきます。全てのデータが追加された後、hash_final()関数を呼び出すと、それまでに入力されたデータ全体に基づいて最終的なハッシュ値が計算され、結果として返されます。

この関数は、計算されたハッシュ値をデフォルトで小文字の16進数文字列として返しますが、オプション引数binarytrueを指定することで、生バイナリ形式のハッシュ値を取得することも可能です。hash_final()の呼び出しによって、ハッシュ計算に使用された内部コンテキストは自動的に閉じられ、関連するリソースが解放されます。これにより、大規模なデータ処理やストリームデータのハッシュ計算においても、安全かつ効率的に利用できます。

構文(syntax)

1<?php
2
3$context = hash_init('sha256');
4hash_update($context, 'Hello, world!');
5$hash = hash_final($context);
6echo $hash;
7
8?>

引数(parameters)

HashContext $context, bool $binary = false

  • HashContext $context: hash_init() で生成されたハッシュコンテキストオブジェクト
  • bool $binary = false: true を指定すると、バイナリ形式でハッシュ値が返されます

戻り値(return)

string

ハッシュコンテキストから最終的なハッシュ値を文字列として取得します。

サンプルコード

PHP hash_final でファイルのハッシュをストリーミング計算する

1<?php
2
3/**
4 * ストリーミング方式でファイルのハッシュ値を計算します。
5 * hash_init, hash_update, hash_final を使用することで、
6 * 大きなファイルでもメモリを大量に消費せずにハッシュ計算が可能です。
7 * この方法は、ファイル全体を一度にメモリに読み込む hash_file 関数と同等の結果を、
8 * チャンク(塊)ごとに処理することで実現します。
9 *
10 * @param string $filePath ハッシュ計算を行うファイルのパス。
11 * @param string $algo 使用するハッシュアルゴリズム (例: 'md5', 'sha256', 'sha512')。
12 * @param bool $binary true の場合、ハッシュは生のバイナリ形式で返されます。
13 *                      false (デフォルト) の場合、小文字の16進数形式で返されます。
14 * @return string|false ファイルのハッシュ値。ファイルが存在しないか読み取れない場合は false を返します。
15 */
16function calculateFileHashWithStream(string $filePath, string $algo = 'sha256', bool $binary = false): string|false
17{
18    // ファイルが存在し、読み込み可能かチェック
19    if (!is_file($filePath) || !is_readable($filePath)) {
20        return false;
21    }
22
23    // ハッシュコンテキストを初期化
24    $context = hash_init($algo);
25
26    // ファイルをバイナリ読み込みモードでオープン
27    $handle = fopen($filePath, 'rb');
28    if ($handle === false) {
29        return false;
30    }
31
32    // ファイルの終端までチャンクごとに読み込み、ハッシュを更新
33    // 8192バイト(8KB)ずつ読み込むのが一般的なパフォーマンスの良いサイズです。
34    while (!feof($handle)) {
35        $chunk = fread($handle, 8192);
36        hash_update($context, $chunk);
37    }
38
39    // ファイルハンドルをクローズ
40    fclose($handle);
41
42    // 最終的なハッシュ値を取得
43    // ここで hash_final が呼び出され、蓄積されたデータから最終的なハッシュ値が生成されます。
44    return hash_final($context, $binary);
45}
46
47// --- サンプルコードの実行 ---
48
49// テストファイルを作成
50$testFilePath = 'sample_file_for_hash.txt';
51$testContent = "これはPHPのhash_final関数の動作を示すためのテストファイルです。\n";
52$testContent .= "ストリーミング方式でファイルを読み込み、ハッシュを計算します。\n";
53$testContent .= "この方法により、大きなファイルでもメモリ効率良く処理できます。\n";
54$testContent .= "最終的にhash_file関数と同じ結果が得られることを確認します。\n";
55$testContent .= "SHA-256アルゴリズムを使用します。\n";
56
57if (file_put_contents($testFilePath, $testContent) === false) {
58    echo "エラー: テストファイルの作成に失敗しました。\n";
59    exit(1);
60}
61
62echo "テストファイル '{$testFilePath}' を作成しました。\n\n";
63
64// ストリーミング方式 (hash_init, hash_update, hash_final) でハッシュを計算
65$streamHash = calculateFileHashWithStream($testFilePath, 'sha256');
66
67if ($streamHash !== false) {
68    echo "ストリーミング方式 (calculateFileHashWithStream) による SHA-256 ハッシュ:\n";
69    echo "  {$streamHash}\n\n";
70} else {
71    echo "エラー: ストリーミング方式でのハッシュ計算に失敗しました。\n\n";
72}
73
74// 比較のために hash_file 関数で同じファイルのハッシュを計算
75// hash_file は内部的にストリーミング処理を行うため、メモリ効率が良い関数です。
76$fileHash = hash_file('sha256', $testFilePath);
77
78if ($fileHash !== false) {
79    echo "hash_file 関数による SHA-256 ハッシュ (比較用):\n";
80    echo "  {$fileHash}\n\n";
81} else {
82    echo "エラー: hash_file 関数でのハッシュ計算に失敗しました。\n\n";
83}
84
85// 両方の結果を比較
86if ($streamHash !== false && $fileHash !== false) {
87    if ($streamHash === $fileHash) {
88        echo "結果の比較: ストリーミング方式と hash_file のハッシュは一致しました。\n";
89        echo "これは、hash_init, hash_update, hash_final を使った方法が\n";
90        echo "hash_file と同等の正確な結果を生成することを示しています。\n";
91    } else {
92        echo "結果の比較: ハッシュが一致しませんでした。何らかの問題が発生しています。\n";
93    }
94}
95
96// テストファイルを削除
97if (file_exists($testFilePath)) {
98    unlink($testFilePath);
99    echo "\nテストファイル '{$testFilePath}' を削除しました。\n";
100}
101
102?>

このサンプルコードは、PHPのhash_final関数が、hash_initおよびhash_updateと連携して、大きなファイルのハッシュ値をメモリ効率良く計算する方法を実演しています。hash_finalは、hash_initで初期化され、ファイルデータなどの情報がhash_updateで段階的に追加されたハッシュコンテキストから、最終的なハッシュ値を取り出す役割を担います。第一引数$contextには、これまでのハッシュ計算の過程を保持するHashContextオブジェクトを指定します。第二引数$binaryはオプションで、trueを設定すると生バイナリ形式のハッシュ値を、false(デフォルト)の場合は一般的な16進数文字列形式で返します。戻り値は、最終的に計算されたハッシュ値の文字列です。

サンプルコード内のcalculateFileHashWithStream関数では、ファイルを小さなチャンク(塊)に分割して読み込み、それぞれのチャンクをhash_updateに渡してハッシュコンテキストを更新しています。ファイル全体の読み込みが完了した後、hash_finalを呼び出すことで、すべてのデータに基づいて最終的なハッシュ値が確定されます。このストリーミング方式は、ファイル全体を一度にメモリに読み込む必要がないため、特にサイズの大きなファイルを扱う際にメモリ消費を抑えるのに非常に有効です。コードの実行部分では、この方法で得られたハッシュ値と、PHPに組み込みのhash_file関数で直接計算したハッシュ値を比較し、両者が完全に一致することを確認しています。これにより、hash_inithash_updatehash_finalの組み合わせが、hash_fileと同様に正確で信頼性の高いハッシュ計算を提供できることが示されています。

hash_final関数は、hash_initで初期化し、hash_updateでデータを追加したハッシュ計算の最終段階で、最終的なハッシュ値を取得するために使用します。この関数単体では機能せず、必ず一連のストリーミング処理の一部として利用されます。大きなファイルを扱う際に、ファイル全体をメモリに読み込まずに効率良くハッシュ計算ができる点が重要です。引数$binarytrueにすると生のバイナリ形式で、false(デフォルト)の場合は小文字の16進数形式でハッシュ値が返されますので、用途に合わせて指定してください。ファイル処理を行う際は、必ずfopenfcloseでファイルハンドルを適切に管理し、ファイルの存在チェックや読み込みエラーに対するハンドリングを忘れずに行うことが安全なコードを書く上で非常に大切です。一般的にはhash_file関数が手軽ですが、より柔軟な制御が必要な場合にこのストリーミング方式が役立ちます。

PHPでストリーミングハッシュを計算する

1<?php
2
3/**
4 * 複数のデータチャンクからSHA-256ハッシュを計算するサンプルコード。
5 * hash_init, hash_update, hash_final の一連の流れを示します。
6 * これは、大きなファイルやストリームデータをメモリに一度にロードせず、
7 * 部分的にハッシュを計算する際によく使用されます。
8 *
9 * @param string $dataPart1 最初のデータ部分
10 * @param string $dataPart2 2番目のデータ部分
11 * @return string 計算されたハッシュ値 (16進数形式)
12 */
13function calculateStreamingHash(string $dataPart1, string $dataPart2): string
14{
15    // 1. ハッシュコンテキストの初期化
16    // 'sha256' アルゴリズムを使用してハッシュコンテキストを作成します。
17    // このコンテキストは、ハッシュ計算の状態を保持します。
18    $context = hash_init('sha256');
19
20    // 2. 最初のデータ部分をハッシュに追加
21    // hash_update() を呼び出すことで、データをコンテキストに追加し、ハッシュ計算を更新します。
22    // これはデータをストリームのように扱えることを意味します。
23    hash_update($context, $dataPart1);
24
25    // 3. 2番目のデータ部分をハッシュに追加
26    // hash_update() は複数回呼び出すことができます。
27    // ここでは、別のデータ部分を追加して、ハッシュ計算を継続します。
28    hash_update($context, $dataPart2);
29
30    // 4. 最終的なハッシュ値の取得
31    // hash_final() は、現在のコンテキストから最終的なハッシュ値を計算して返します。
32    // 第2引数を true にするとバイナリ形式で返されますが、デフォルトでは16進数形式の文字列です。
33    $finalHash = hash_final($context);
34
35    return $finalHash;
36}
37
38// --------------------------------------------------------------------------
39// サンプルコードの実行部分
40// --------------------------------------------------------------------------
41
42// サンプルデータの定義
43$firstChunk = "このデータは最初の部分です。";
44$secondChunk = "そして、これは後から追加される2番目の部分です。";
45$thirdChunk = "さらに、もう一つの部分を追加してみましょう。"; // 追加のデータチャンクの例
46
47echo "元のデータ:\n";
48echo "  パート1: '" . $firstChunk . "'\n";
49echo "  パート2: '" . $secondChunk . "'\n";
50echo "  パート3: '" . $thirdChunk . "'\n\n";
51
52// calculateStreamingHash関数を呼び出してハッシュを計算
53// ここでは関数内で2つのパートを扱っていますが、必要に応じて関数内でhash_updateをさらに呼び出すことができます。
54$hashResult = calculateStreamingHash($firstChunk, $secondChunk . $thirdChunk);
55
56echo "計算されたSHA-256ハッシュ: " . $hashResult . "\n\n";
57
58// 全てのデータを一度にハッシュ化した場合と比較 (hash関数を使用)
59$allDataCombined = $firstChunk . $secondChunk . $thirdChunk;
60$singleHash = hash('sha256', $allDataCombined);
61
62echo "全てのデータを一度にハッシュ化した場合 (hash関数): " . $singleHash . "\n";
63
64// 結果が一致することを確認
65if ($hashResult === $singleHash) {
66    echo "ストリーミングハッシュと一括ハッシュの結果は一致します。\n";
67} else {
68    echo "ハッシュの結果が一致しません。\n";
69}
70
71?>

PHPのhash_final関数は、hash_initで初期化され、hash_updateで段階的に追加されてきたハッシュ計算処理を完了させ、最終的なハッシュ値を取得するために使用します。この関数は、特に大きなファイルやストリームデータを一度にメモリにロードせず、複数のデータチャンクに分けてハッシュを計算する際に重要な役割を果たします。

引数には、hash_init関数が返したハッシュ計算の状態を保持するHashContextオブジェクトを渡します。オプションの第2引数$binaryは、ハッシュ値の出力形式を制御し、trueを指定するとバイナリ形式で、デフォルトのfalseでは16進数形式の文字列としてハッシュ値が返されます。戻り値は、計算された最終的なハッシュ値を示す文字列です。

サンプルコードでは、hash_initでSHA-256アルゴリズムのハッシュコンテキストを準備した後、hash_updateを複数回呼び出して異なるデータ部分をコンテキストに追加しています。このようにしてデータを分割して段階的にハッシュ計算を進めることができます。そして、最後にhash_finalが呼ばれることで、それまでにhash_updateで追加された全てのデータに基づいた、一つのまとまった最終ハッシュ値が生成されます。この結果は、全てのデータを連結して一度にハッシュ関数に渡した場合と同じになります。

hash_finalは、hash_initで初期化しhash_updateで順次追加されたデータのハッシュ計算を完了させ、最終的なハッシュ値を取得する関数です。これは、大きなファイルをメモリに一度に読み込まず、部分的に処理するストリーミングハッシュに適しています。 hash_finalの第2引数$binarytrueにするとハッシュ値はバイナリ形式で返りますが、ウェブ表示や文字列操作ではデフォルトの16進数形式が扱いやすいでしょう。hash_updateは複数回呼び出し可能で、データを分割して追加しても最終ハッシュ値は結合データと一致します。 パスワードの保存などセキュリティが重要な用途には、このハッシュ関数ではなくpassword_hash関数を必ず使用してください。

関連コンテンツ

関連IT用語

関連プログラミング言語