ダウンロードしたファイルが改ざんされていないか確認したいときや、ファイルの内容が同じかどうかを比較したいときは、openssl dgstでハッシュ値を計算する。
$ openssl dgst -sha256 a.txt
SHA2-256(a.txt)= 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
-sha256の部分でハッシュアルゴリズムを指定する。標準入力からも読み込める。
$ echo -n hello | openssl dgst -sha256
SHA2-256(stdin)= 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
実行例はUbuntu 24.04のOpenSSL 3.0.13のもの。
ハッシュアルゴリズムを選ぶ
-sha256のほかに、-sha1、-sha512、-sha3-256、-md5などを指定できる。-md5と-sha1は衝突攻撃が可能であり、改ざん検知には向かない。チェックサムの突き合わせなど、配布元が指定している場合に使う。
$ openssl dgst -sha512 a.txt
$ openssl dgst -sha3-256 a.txt
$ openssl dgst -md5 a.txt
MD5(a.txt)= 5d41402abc4b2a76b9719d911017c592
アルゴリズムを省略した場合、OpenSSL 3.0ではSHA-256が使われる。
使えるアルゴリズムの一覧はopenssl list -digest-algorithmsで確認できる。存在しないアルゴリズムを指定するとエラーになる。
$ openssl dgst -sha257 a.txt
dgst: Unknown option or message digest: sha257
dgst: Use -help for summary.
複数のファイルのハッシュ値をまとめて計算する
ファイル名を複数並べると、1行ずつ出力される。
$ openssl dgst -sha256 a.txt b.txt
SHA2-256(a.txt)= 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
SHA2-256(b.txt)= 73cb3858a687a8494ca3323053016282f3dad39d42cf62ca4e79dda2aac7d9ac
ディレクトリは指定できない。Is a directoryというエラーになる。ディレクトリ配下のファイルをまとめて処理したい場合は、findとxargsを組み合わせる。
sha256sumと同じ形式で出力する
-rを付けると、sha256sumと同じ「ハッシュ値とファイル名」の形式で出力する。
$ openssl dgst -sha256 -r a.txt
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 *a.txt
ファイル名の前の*はバイナリモードを表す。sha256sumの出力はファイル名の前が空白2つであり、*の有無だけが異なる。
-rの出力をファイルに保存すると、sha256sum -cで検証できる。
$ openssl dgst -sha256 -r a.txt b.txt > SUMS
$ sha256sum -c SUMS
a.txt: OK
b.txt: OK
a.txtを書き換えてから再度検証すると、ハッシュ値が一致しないファイルを検出できる。
$ echo tamper >> a.txt
$ sha256sum -c SUMS
a.txt: FAILED
b.txt: OK
sha256sum: WARNING: 1 computed checksum did NOT match
macOSではsha256sumがない。代わりにshasum -a 256 -c SUMSを使う。
HMACを計算する
共通の秘密鍵を使ったHMACは、-hmacで鍵を指定して計算する。
$ openssl dgst -sha256 -hmac secret a.txt
HMAC-SHA2-256(a.txt)= 88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b
Webhookの署名検証など、送信側と同じ鍵でHMACを計算して突き合わせる用途で使う。
鍵が16進数のバイト列で与えられている場合は、-mac HMAC -macopt hexkey:[鍵]を使う。-hmac secretと-macopt hexkey:736563726574は同じ鍵を表すため、同じ値になる。
$ openssl dgst -sha256 -mac HMAC -macopt hexkey:736563726574 b.txt
HMAC-SHA2-256(b.txt)= 40a27deb5b58930e4e3ddbea15abe4f7eb96db721defd15a287ce0299610915f
-hmacで鍵を指定するとシェルの履歴やプロセス一覧に鍵が残る。本番の鍵を扱う場合は、環境変数やファイル経由で渡す方法を検討する。
出力形式を変える
ハッシュ値だけを取り出す
ファイル名などを除き、ハッシュ値のみが欲しい場合は-rの出力からcutで取り出す。
$ openssl dgst -sha256 -r a.txt | cut -d' ' -f1
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
コロン区切りにする
-cを付けると、ハッシュ値を1バイトずつコロンで区切って出力する。証明書のフィンガープリントと同じ表記に揃えたい場合が該当する。
$ openssl dgst -sha256 -c a.txt
SHA2-256(a.txt)= ec:7b:9f:f4:5e:fb:d7:19:f7:5f:29:ef:17:7b:93:fc:9b:4c:46:7f:a1:bd:b2:30:29:2c:77:2a:ba:9f:5b:79
バイナリやBase64で出力する
-binaryを付けると、ハッシュ値をバイナリのまま出力する。Base64に変換したい場合は、openssl base64に渡す。
$ openssl dgst -sha256 -binary a.txt | openssl base64
LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
Subresource Integrity(SRI)のintegrity属性に書く値は、この形式である。sha256-を先頭に付ける。
バージョンによる違い
OpenSSL 3.5や3.6でも、ここまでの例の出力は同じである。
macOS標準の/usr/bin/openssl(LibreSSL 3.3.6)では、出力の先頭のアルゴリズム名が異なる。
| 実行環境 | 通常の出力 | HMACの出力 |
|---|---|---|
| OpenSSL 3.x | SHA2-256(a.txt)= ... | HMAC-SHA2-256(a.txt)= ... |
| LibreSSL 3.3.6 | SHA256(a.txt)= ... | HMAC-SHA256(a.txt)= ... |
ハッシュ値の部分は同じである。出力をパースするスクリプトでは、アルゴリズム名の表記に依存しないよう、-rを使うかcutで右辺を取り出す。
