wget 脚本,但仅当脚本的 SHA256 与单行匹配时才将其通过管道传输到 bash

maq*_*aqp 10 command-line bash scripts wget

wget http://example.com/install.sh -O - | bash自动运行脚本,但由于可能的 (TLS) MITM 攻击等,这是不安全的。是否可以构建一个下载脚本的单行,但仅当它的哈希与单行中指定的哈希匹配时才执行它?如果单行可以打印一些类似于Warning! Hash mismatch哈希检查失败的内容,那就太好了。

Byt*_*der 6

所以你要下载并运行http://example.com/install.sh.

现在,我假设您将其 SHA256 哈希值本地存储在一个名为my-sha256.txt. 该文件仅包含散列本身和一个 Unix 样式的换行符,因此其大小必须恰好为 65 字节。您可以通过简单地运行以下命令来创建它:

sha256sum ORIGINAL_FILE.SH | grep -Eo '^\w+' > my-sha256.txt
Run Code Online (Sandbox Code Playgroud)

您如何将这个哈希文件从您的开发机器分发到客户端不是这个答案的一部分(但是,您可能会澄清您的问题并要求我根据您的详细规范更新这部分)。


您的客户端必须运行以下载、验证和成功执行的实际命令,脚本可能如下所示:

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"
Run Code Online (Sandbox Code Playgroud)

没有空格的稍微缩短和丑陋的版本:

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"
Run Code Online (Sandbox Code Playgroud)

放置在多行以提高可读性:

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"
Run Code Online (Sandbox Code Playgroud)

如果您想直接在命令中提供哈希作为字符串而不是从文件中读取,只需使用我上面的原始命令版本之一并替换my-sha256.txtwith的出现<(echo YOUR_HASH),当然插入您的真实哈希而不是“YOUR_HASH”占位符。

解释:

脚本/单行程序首先使用mktemp(使用系统的临时文件夹/tmp)创建一个临时文件。
然后它用于wget从指定的 URL 下载您的安装脚本并将其保存在临时文件中。
现在我们计算它的哈希和,只过滤输出中的哈希值sha256sum,并将其与我们存储在 out 中的值进行比较my-sha256.txt
如果两个哈希值相等,我们将bash使用临时脚本文件作为参数进行调用,否则我们echo FAIL或您可能会输出自定义错误消息。
最后,我们通过在两种情况下删除临时文件来进行清理。


但是,回到安全分发哈希以验证原始脚本的问题上,上面的这个解决方案对您没有多大帮助,因为它通过创建另一个同类解决了一个问题。

您实际上应该做的是创建一个 GPG 密钥对(并将您的公钥发布到密钥服务器),用它对您的脚本进行签名并提供压缩的签名二进制文件以供下载。然后让客户端gpg再次使用验证和解密脚本并成功运行它。

  • 我想我明白了:`gpg --keyserver pgp.mit.edu --recv-keys &lt;GPG pub key SHA1 指纹&gt; &amp;&amp; wget https://example.com/install.sh{,.asc} -q &amp;&amp; gpg --verify install.sh{.asc,} &amp;&amp; bash install.sh` (2认同)