sha256sum入門|ファイルの中身が同じか確かめる

sha256sum入門|ファイルの中身が同じか確かめる

ダウンロードした ZIP が途中で壊れていないか、バックアップしたファイルが元と本当に同じか。

見た目では判断できないこの手の確認を、1コマンドで片付けてくれるのが sha256sum です。

今回は Ubuntu 22.04.5(GNU coreutils 8.32)のサンドボックスで実際に叩きながら、基本の使い方を整理しました。

ハッシュ値は中身の指紋

sha256sum はファイルの中身を読んで、64文字の16進数を計算します。

同じ中身なら必ず同じ値になり、1バイトでも違えば全く別の値になるのが肝心なところ。

末尾の1文字だけを変えて比べると、値がまるごと入れ替わるのが分かります。

$ printf 'hello\n' > a.txt
$ printf 'hellp\n' > b.txt
$ sha256sum a.txt b.txt
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03  a.txt
bf8c83416f31143ee2fa5db7ebbbb54589626c4c2046a91d28545bc403e3cda6  b.txt

「o」と「p」の違いしかないのに、共通する部分は1文字もありません。

だからこそ、値が一致すれば中身も一致していると言い切れるのです。

まずは1ファイルで試す

出力はハッシュ値とファイル名をスペース2つで区切った形です。

この形式は後で出てくる検証モードがそのまま読み取れるので、自分で整形しないほうが幸せになります。

標準入力から流し込むこともでき、そのときファイル名の欄はハイフンになりました。

$ printf 'hello\n' | sha256sum
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03  -

-c でまとめて検証する

sha256sum の本領はこちらです。

先に一覧ファイルを作っておき、あとから -c で突き合わせます。

$ sha256sum a.txt b.txt > SHA256SUMS
$ sha256sum -c SHA256SUMS
a.txt: OK
b.txt: OK

この状態で b.txt の中身を書き換えてから、もう一度検証してみましょう。

$ printf 'hacked\n' > b.txt
$ sha256sum -c SHA256SUMS
sha256sum: WARNING: 1 computed checksum did NOT match
a.txt: OK
b.txt: FAILED
$ echo $?
1

壊れた行が FAILED で名指しされ、終了ステータスも 1 になります

スクリプトから呼ぶなら、この終了ステータスだけを見れば十分。

OK 行が邪魔なときは –quiet を足すと、失敗した行だけが残ります。

配布元の値と1行だけ突き合わせる

公式サイトにハッシュ値が1つだけ書いてある、というケースも珍しくありません。

その場合は一覧ファイルを作らず、標準入力から -c に渡すのが手軽です。

$ printf '5891b5b5...be03  a.txt\n' | sha256sum -c -
a.txt: OK

注意点は大文字と小文字。

配布元が大文字で書いている場合、sha256sum の出力は小文字なので目視だと一致を見落とします。

$ EXPECT="5891B5B5...BE03"
$ ACTUAL=$(sha256sum c.txt | cut -d' ' -f1)
$ [ "$(printf %s "$EXPECT" | tr 'A-Z' 'a-z')" = "$ACTUAL" ] && echo MATCH || echo MISMATCH
MATCH

ディレクトリを丸ごと比べる

sha256sum にディレクトリを渡すと、エラーになって何も出ません。

$ sha256sum d
sha256sum: d: Is a directory

フォルダ単位で比べたいときは、find で列挙してから xargs へ渡します。

並び順が違うと差分だらけになるので、sort をはさむのが要点です。

$ (cd d && find . -type f -print0 | sort -z | xargs -0 sha256sum) > A.txt
$ (cd e && find . -type f -print0 | sort -z | xargs -0 sha256sum) > B.txt
$ diff A.txt B.txt
2c2
< 3bb2abb6...0877  ./sub/2.txt
---
> c865f6c5...70ab  ./sub/2.txt

中身が違うファイルだけが行として浮かび上がりました。

コピー先が本当に同じか確かめたいときは、これがいちばん確実な方法。

md5sum と sha256sum、どちらを使うか

100MB のランダムなファイルで所要時間を測ってみました。

md5    0.10 s
sha256 0.20 s
sha512 0.14 s

md5 が速いのは想像どおりですが、sha512 が sha256 より速いのは意外に思うかもしれません。

sha512 は64ビット単位で計算するアルゴリズムなので、いまの64ビットCPUでは有利に働くのです。

速度差は 100MB で 0.1 秒程度なので、実用上は素直に sha256sum を選んでおけば困りません。

md5 は意図的に同じ値を持つ別ファイルを作れることが知られており、改ざん検知の用途では使わないのが原則です。

つまずきやすいところ

  • 一覧ファイルに書式の崩れた行があると WARNING: 1 line is improperly formatted が出る
  • 一覧に書いたファイルが存在しないときは –ignore-missing で無視できる
  • -b を付けるとファイル名の前にアスタリスクが付く(バイナリモードの印)
  • ハッシュ値は暗号ではないので、値から元のファイルは復元できない

最後に

sha256sum は覚えることが少ないわりに、「同じかどうか」を人間の目より正確に答えてくれる道具です。

とくに -c による一括検証は、バックアップの健全性チェックにそのまま使えます。

詳しいオプションは GNU Coreutils の公式マニュアル にまとまっているので、迷ったら一次情報を当たってください。

関連するコマンドの入門記事も置いてあります。

xargs入門|パイプの結果を次のコマンドの引数に渡す基本
diff入門|2つのファイルの違いを行単位で見つける基本

以上です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA