wget http://example.com/install.sh -O - | bash
はスクリプトを自動的に実行しますが、可能性のある(TLS)MITM攻撃などにより、これは安全ではありません。スクリプトをダウンロードするワンライナーを作成することは可能ですが、ハッシュがワンライナーで指定されたものと一致する場合にのみ実行されますか?ハッシュチェックが失敗した場合、ワンライナーがWarning! Hash mismatch
のようなものを出力するといいでしょう。
したがって、http://example.com/install.sh
をダウンロードして実行します。
ここでは、my-sha256.txt
というファイルにSHA256ハッシュがローカルに保存されていると仮定します。ファイルにはハッシュ自体とUnixスタイルの改行文字のみが含まれているため、サイズは正確に65バイトでなければなりません。これを実行するだけで作成できます:
sha256sum ORIGINAL_FILE.SH | grep -Eo '^\w+' > my-sha256.txt
このハッシュファイルを開発マシンからクライアントに配布する方法は、この回答の一部ではありません(ただし、質問を明確にし、詳細な仕様に基づいてこの部分を更新するよう依頼する場合があります)。
クライアントが実行、スクリプトのダウンロード、検証、成功時に実行する必要がある実際のコマンドは次のようになります。
t=$(mktemp) && wget 'http://example.com/install.sh' -qO "$t" && if sha256sum "$t" | grep -Eo '^\w+' | cmp -s my-sha256.txt ; then bash "$t" ; else echo FAIL ; fi ; rm "$t"
空白のないわずかに短くていバージョン:
t=$(mktemp)&&wget 'http://example.com/install.sh' -qO"$t"&&if sha256sum "$t"|grep -Eo '^\w+'|cmp -s my-sha256.txt;then bash "$t";else echo FAIL;fi;rm "$t"
読みやすくするために複数の行に配置:
t=$(mktemp) &&
wget 'http://example.com/install.sh' -qO "$t" &&
if sha256sum "$t" | grep -Eo '^\w+' | cmp -s my-sha256.txt
then bash "$t"
else echo FAIL
fi
rm "$t"
ファイルから読み取るのではなく、コマンド内のハッシュを文字列として直接提供する場合は、上記の元のコマンドバージョンのいずれかを使用し、my-sha256.txt
の出現を<(echo YOUR_HASH)
に置き換えて、実際のハッシュを挿入しますもちろん、「YOUR_HASH」プレースホルダーの代わりに。
説明:
スクリプト/ワンライナーは、最初にmktemp
を使用して一時ファイルを作成します(システムの一時フォルダー/tmp
を使用します)。
次に、wget
を使用して、指定されたURLからインストールスクリプトをダウンロードし、一時ファイルに保存します。
今、そのハッシュ和を計算し、sha256sum
の出力からハッシュ値のみをフィルターし、それをoutmy-sha256.txt
に保存したものと比較します。
両方のハッシュが等しい場合、一時スクリプトファイルを引数としてbash
を呼び出します。それ以外の場合はecho FAIL
を呼び出すか、カスタムエラーメッセージを出力できます。
最後に、どちらの場合も一時ファイルを削除してクリーンアップします。
ただし、元のスクリプトを検証するためにハッシュを安全に配布する問題に戻ると、上記の解決策は、同じ種類の別の問題を作成することで問題を解決するため、あまり役に立ちません。
実際に行うべきことは、GPGキーペアを作成し(公開キーをキーサーバーに公開する)、それを使用してスクリプトに署名し、ダウンロード用の圧縮署名付きバイナリを提供することです。次に、クライアントがgpg
を使用してスクリプトを再度検証および復号化し、成功時に実行できるようにします。
GPGフィンガープリントは安全でないSHA-1ハッシュを使用するため、以下は公開鍵から計算された非公式のSHA256ハッシュによる認証を許可するワンライナーです。
gpg --export <key ID> | sha256sum
コマンド:
h="<SHA256 hash of exported public key>"; fp="<PGP key SHA1 fingerprint>"; f='key.pub'; gpg --keyserver pgp.mit.edu --recv $fp && gpg --export $fp > $f && if sha256sum $f | grep -Eo '^\w+' | cmp -s <(echo $h); then rm $f && wget https://example.com/install.sh{,.asc} -q && gpg --verify install.sh{.asc,} && bash install.sh; else rm $f; echo "ERROR: Signing key had invalid SHA256 hash"; fi;