在Bash中使用HMAC-SHA1

121

有没有一个Bash脚本可以生成HMAC-SHA1哈希值?

我正在寻找与以下PHP代码等效的内容:

hash_hmac("sha1", "value", "key");
5个回答

236

我知道这不完全是您要求的,但是没有必要重新发明轮子并编写Bash版本。

您可以在脚本中使用openssl命令来生成哈希值。

[me@home] echo -n "value" | openssl dgst -sha1 -hmac "key"
57443a4c052350a44638835d64fd66822f813319

或者简单地说:

[me@home] echo -n "value" | openssl sha1 -hmac "key"
57443a4c052350a44638835d64fd66822f813319

记得在使用echo时加上-n,否则会自动添加一个换行符到字符串末尾,从而改变数据和哈希值。

这个命令来自于OpenSSL包,该包应该已经安装好(或者可以很容易地安装)在你选择的Linux/Unix、Cygwin等系统中。

请注意,旧版本的openssl(例如随RHEL4一起发布的版本)可能不提供-hmac选项。


作为另一种解决方案,但主要是为了证明结果相同,我们也可以从命令行调用PHP的hmac_sha1()函数:

[me@home]$ echo '<?= hash_hmac("sha1", "value", "key") ?>' | php
57443a4c052350a44638835d64fd66822f813319

1
@Marcin:你能引用一下来源吗? - sehe
7
我有一个与HMAC-SHA256相关的问题。解决方案相同,但是将sha1替换为sha256 :-) - mogsie
1
是的,你可以这样做,但要注意文件中的换行符也会被视为值的一部分。 - Shawn Chin
2
@ShawnChin,在这个例子中,密钥的编码/格式是什么?它应该像使用“openssl genrsa”创建的私钥一样进行base64编码吗?另外,“openssl”文档链接显示404错误。 - Carlos Macasaet
3
这对我在Mac上的操作有效,但在CentOS 7机器上,openssl在哈希之前输出了(stdin)= 。 在openssl命令的末尾添加-binary | xxd -plain可以解决此问题(参见https://unix.stackexchange.com/a/90242/58450)。 - Tim Malone
显示剩余7条评论

43

这是一个类似于PHP中的hash_hmac的Bash函数:

#!/bin/bash

function hash_hmac {
  digest="$1"
  data="$2"
  key="$3"
  shift 3
  echo -n "$data" | openssl dgst "-$digest" -hmac "$key" "$@"
}

# hex output by default
hash_hmac "sha1" "value" "key"

# raw output by adding the "-binary" flag
hash_hmac "sha1" "value" "key" -binary | base64

# other algos also work
hash_hmac "md5"  "value" "key"

这是一个不错的结束方式。+1 - Shawn Chin
+1 因为与所选答案不同,这个回答了所问的问题。(虽然两个都有帮助。) - Alexx Roche
但是,如果数据是多行的,比如XML或JSON体,你该如何将“数据”参数传递给脚本而不失去缩进呢? - HyperioN
@HyperioN如果您的JSON数据存储在文件中,您可以简单地执行以下操作:hash_hmac "sha1" "$(cat your-json-file)" "key"。或者,您也可以通过openssl dgst将文件导入而不使用这个hash_hmac函数。 - Martin
感谢您提供二进制位的资料,这是我缺失的一块。 - jgreen

14

感谢 hash_hmac 函数!但对于我的应用来说这还不够。如果有人好奇的话,我需要使用先前哈希结果作为密钥,多次对相同内容进行哈希,因此密钥是二进制输入(亚马逊 AWS 身份验证签名就是这么创建的)。

所以我需要一种以某种方式提供二进制密钥而不会破坏算法的方法。然后我找到了这个: http://openssl.6102.n7.nabble.com/command-line-hmac-with-key-in-hex-td6754.html

Stephen Henson 的回复要求 hash_hmac 函数以十六进制格式返回值。因此需要执行以下操作:

$ echo -n "$data" | openssl dgst "-$digest" -hmac "$key" | sed -e 's/^.* //'

那么下一个调用需要将密钥提供为十六进制:

$ echo -n "$data" | openssl dgst "-$digest" -mac HMAC -macopt "hexkey:$key" | sed -e 's/^.* //'

希望这能对任何人有所帮助,也许是那些试图在AWS上创建bash脚本来使CloudFront条目失效的人(就像我一样!)(我还没有测试过,但我认为这就是我的bash脚本无法正常工作而我的PHP脚本可以的原因...)


0

如果已经安装了node.js,您可以使用HMAC-CLI工具:

npx hmac-cli generate 'value' -h sha1 -s key

返回:

57443a4c052350a44638835d64fd66822f813319

-5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接