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

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

wget http://example.com/install.sh -O - | bash自动运行脚本,但由于可能存在 (TLS) MITM 攻击等,因此这并不安全。是否可以构造一个单行程序来下载脚本,但只有当其哈希值与单行程序中指定的哈希值匹配时才执行该脚本?如果单行程序能够打印出Warning! Hash mismatch哈希值检查失败之类的信息,那就太好了。

答案1

因此您要下载并运行http://example.com/install.sh

目前,我假设您已将其 SHA256 哈希存储在本地名为 的文件中my-sha256.txt。该文件仅包含哈希本身和一个 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并将其与我们存储在 out 中的内容进行比较my-sha256.txt
如果两个哈希值相等,我们将bash使用临时脚本文件作为参数进行调用,否则我们echo FAIL或您可以输出自定义错误消息。
最后,我们通过删除两种情况下的临时文件来进行清理。


然而,回到安全地分发哈希以验证原始脚本的问题,上述解决方案不会对您有太大帮助,因为它通过创建另一个同类问题来解决一个问题。

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

答案2

由于 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;

相关内容