如何在 Shell 中获取字符串的二进制表示?

如何在 Shell 中获取字符串的二进制表示?

我用来openssl dgst -sha1 -binary获取二进制格式的字符串的哈希值。

(我使用-binary标志是因为我的 openssl 版本在默认输出的每个哈希值之前添加了“stdout”,并有助于避免它,因此更容易以二进制格式存储哈希结果以进行进一步处理(所以我可以在我使用时-binary使用)想要十六进制值而不是手动从每个字符串中xxd -p删除“ ”)stdout

openssl dgst -sha1 -binary因此, “Hello!”的二进制输出Cygwin 控制台中的字符串将如下所示:_▒▒"q▒%▒a▒▒▒▒.&C▒0N▒Q▒▒vH&8i

现在,我使用此结果创建一个新变量,并将其与另一个变量连接,该变量的值不是二进制格式(即“World”)。所以我的新变量现在看起来像

_▒▒"q▒%▒a▒▒▒▒.&C▒0N▒Q▒▒vH&8iWorld

然后,我为这个连接字符串生成另一个散列,并将其与使用默认 Java 散列库 ( ) 得到的散列进行比较MessageDigest。然而,在这一步中,通过 shell 和 Java 获得的哈希值不匹配(我需要获得与 Java 端生成的值完全相同的值)。

因此,我认为我的“World”字符串也应该采用二进制格式,以匹配我的 Java 哈希输出(因为只要我为连接的二进制值生成哈希值,所有哈希值都会匹配)。但是,我不知道如何在 shell 中将“World”字符串转换为二进制格式。有任何想法吗?

答案1

你无法存储二进制变量中的数据(二进制数据通常指具有任意字节值的数据,不仅是形成有效字符但不特殊的字节值),bash因为bash不支持将0字节值存储在其变量中(请记住,您不能传递这样的命令参数中的字符串,因为这些是 NUL 分隔字符串)。

zsh不过你可以进去。另请记住,命令替换会删除尾随换行符(0xa 字节,在 Cygwin 上可能有所不同),因此最好read在这里使用:

$ echo 323 | openssl dgst -sha1 -binary | hd
00000000  3a 8b 03 4a 5d 00 e9 07  b2 9e 0a 61 b3 54 db 45  |:..J]......a.T.E|
00000010  63 4b 37 b0                                       |cK7.|
00000014

查看它如何同时包含 0 字节和换行符 (0xa)

$ echo 323 | openssl dgst -sha1 -binary | IFS= LC_ALL=C read -ru0 -k20 var &&
  var=${var}World
$ printf %s $var | hd
00000000  3a 8b 03 4a 5d 00 e9 07  b2 9e 0a 61 b3 54 db 45  |:..J]......a.T.E|
00000010  63 4b 37 b0 57 6f 72 6c  64                       |cK7.World|
00000019

再次注意,您只能将该变量传递给内置命令(printf...)。

现在,如果您想要的只是再次散列它,那么它只是

(echo 323 | openssl dgst -sha1 -binary; printf %s World) |
  openssl dgst -sha1 -binary

不需要变量。

相关内容