为什么......
KEY=$(echo -ne "\x2e\x9e\x93\x83\x8c\xf5\xeb\x78\x2f\x9e\xd7\xbe\xaa\x27\xf6\x1f\xa5\x35\xe3\x37\x4c\x78\x22\xc9\x11\x24\x20\x22\xa6\x3e\x28\x30")
echo -e "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd)"
...产生
0000000: d77d 4050 8184 cbd2 44f0 f6c2 5b95 39d0 .}@P....D...[.9.
0000010: d9b4 bf25 a7ec a4f8 0dac cc00 6b2b 67d4 ...%........k+g.
和...
echo -ne "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary)" | xxd
产生(注意,与第一个输出相比,缺少字节28)?
0000000: d77d 4050 8184 cbd2 44f0 f6c2 5b95 39d0 .}@P....D...[.9.
0000010: d9b4 bf25 a7ec a4f8 0dac cc6b 2b67 d4 ...%.......k+g.
据我所知,openssl的输出通过子管道输出到xxd并不重要。
答案 0 :(得分:4)
由于其强大的C基础,UNIX字符串无法容纳NUL '\0'
个字符。如果要处理可能具有00
字节的原始二进制数据,则需要避免将结果存储在字符串中。在文件和管道中有00
个字节是安全的。
echo -e "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd)"
这里openssl使用嵌入的00
字节吐出二进制数据。由于您将该输出直接传送到xxd
,因此数据保存完好,00
完好无损。
echo -ne "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary)" | xxd
这里openssl的输出在被传送到xxd之前存储在一个字符串中。 $(...)
操作会删除NUL字符,因为这些字符无法成功存储在字符串中。如果它没有将它们剥离出来,那么第一个NUL就会发出字符串结束的信号。
为了它的价值,你可以删除一层回声。 echo "$(command)"
是一种编写command
的复杂方式。
echo -n aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd
答案 1 :(得分:2)
问题是摘要是二进制的(具体来说,它包含一个零字节),而shell将c-strings作为参数传递给它的命令(例如echo
),而那些不能包含0 bytes(/ null字符)。如果你看一下丢失的字节,那就是" 00"十六进制您可以使用字符串" aws4_request888"更清楚地看到这一点:
$ KEY=$(echo -ne "\x2e\x9e\x93\x83\x8c\xf5\xeb\x78\x2f\x9e\xd7\xbe\xaa\x27\xf6\x1f\xa5\x35\xe3\x37\x4c\x78\x22\xc9\x11\x24\x20\x22\xa6\x3e\x28\x30")
$ echo -e "$(echo -en aws4_request888 | openssl dgst -sha256 -hmac "$KEY" -binary | xxd)"
0000000: 3939 a1b7 b334 22e3 7ab6 d7f0 32be 2f62 99...4".z...2./b
0000010: e353 72f9 3152 a923 a3e3 0000 0006 85fb .Sr.1R.#........
$ echo -ne "$(echo -en aws4_request888 | openssl dgst -sha256 -hmac "$KEY" -binary)" | xxd
0000000: 3939 a1b7 b334 22e3 7ab6 d7f0 32be 2f62 99...4".z...2./b
0000010: e353 72f9 3152 a923 a3e3 0685 fb .Sr.1R.#.....
在这种情况下,摘要有三个空字节,它们都消失了。
这里唯一真正的解决方案是避免通过shell参数,变量等传递二进制数据(也可能包括$KEY
)。 (管道,另一方面,处理二进制就好了。)
如果你需要处理shell中的二进制数据,可以在存储之前将其转换为十六进制(hexvar=$(somethingthatproducesbinary | xxd -p
),然后再转换为二进制文件以供使用(echo "$hexvar" | xxd -r -p | somethingthatreadsbinary
)。