HMAC-SHA1 in Bash

95

Gibt es ein Bash-Skript, um einen HMAC-SHA1Hash zu generieren ?

Ich suche etwas, das dem folgenden PHP-Code entspricht:

hash_hmac("sha1", "value", "key");
Kennzeichen
quelle

Antworten:

185

Mir ist klar, dass dies nicht genau das ist, wonach Sie fragen, aber es macht keinen Sinn, das Rad neu zu erfinden und eine Bash-Version zu schreiben.

Sie können einfach den opensslBefehl verwenden, um den Hash in Ihrem Skript zu generieren.

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

Oder einfach:

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

Denken Sie daran, -nmit zu verwenden, da echosonst ein Zeilenumbruchzeichen an die Zeichenfolge angehängt wird und Ihre Daten und der Hash geändert werden.

Dieser Befehl stammt aus dem OpenSSL-Paket, das bereits unter Linux / Unix, Cygwin und ähnlichen Geräten Ihrer Wahl installiert (oder einfach installiert) werden sollte.

Beachten Sie, dass ältere Versionen von openssl(z. B. die mit RHEL4 gelieferte) möglicherweise nicht die -hmacOption bieten .


Als alternative Lösung, aber hauptsächlich um zu beweisen, dass die Ergebnisse gleich sind, können wir auch PHPs hmac_sha1()über die Befehlszeile aufrufen :

[me@home]$ echo '<?= hash_hmac("sha1", "value", "key") ?>' | php
57443a4c052350a44638835d64fd66822f813319
Shawn Chin
quelle
OpenSSL-Implementierungen sind sehr langsam. Wenn Sie es gelegentlich tun müssen, ist das in Ordnung, aber wenn Sie versuchen, große Mengen an Hashes zu berechnen, möchten Sie verschiedene Wege untersuchen.
Marcin
1
@Marcin: Kannst du damit eine Quelle zitieren?
sehe
6
Ich hatte die gleiche Frage mit HMAC-SHA256. Die gleiche Lösung, wird aber sha1ersetzt durch sha256:-)
Mogsie
1
Ja, das können Sie, aber achten Sie auf Zeilenumbrüche in Ihrer Datei, da dies ebenfalls als Teil des Werts angesehen wird.
Shawn Chin
1
@ShawnChin, in diesem Beispiel, wie lautet die Codierung / das Format des Schlüssels? Sollte es sich um eine Base64-Codierung wie einen privaten Schlüssel handeln, der mit erstellt wurde openssl genrsa? Außerdem führt der OpenSL-Dokumentationslink zu einem 404.
Carlos Macasaet
39

Hier ist eine Bash-Funktion, die wie hash_hmacin PHP funktioniert :

#!/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"
Martin
quelle
Das ist eine schöne Art, es zusammenzufassen. +1
Shawn Chin
+1, da diese im Gegensatz zur ausgewählten Antwort die gestellte Frage beantwortet. (Obwohl beide hilfreich sind.)
Alexx Roche
Aber wie übergeben Sie das Argument 'data' an das Skript, wenn es mehrzeilig ist? Wie ein XML- oder JSON-Body, ohne die Einrückung zu verlieren.
HyperioN
@HyperioN Wenn Sie Ihre JSON-Daten in einer Datei haben, können Sie dies einfach tun : hash_hmac "sha1" "$(cat your-json-file)" "key". Alternativ können Sie Ihre Datei auch einfach weiterleiten, openssl dgstohne diese hash_hmacFunktion zu verwenden.
Martin
9

Danke für die hash_hmac Funktion! Für meine Bewerbung hat es aber nicht gereicht. Für den Fall, dass sich jemand wunderte, musste ich das Zeug mehrmals mit einem Schlüssel neu hashen, der das Ergebnis des vorherigen Hashings war und daher eine binäre Eingabe ist. (Die Amazon AWS-Authentifizierungssignatur wird wie folgt erstellt.)

Was ich also brauchte, war eine Möglichkeit, den Binärschlüssel auf eine Weise bereitzustellen, die den Algorithmus nicht beschädigen würde. Dann fand ich dies: http://openssl.6102.n7.nabble.com/command-line-hmac-with-key-in-hex-td6754.html

Für die Antwort von Stephen Henson muss die Funktion hash_hmac den Wert im Hex-Format zurückgeben. Es muss also Folgendes wiedergeben:

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

Dann müsste der nächste Aufruf den Schlüssel als hexit bereitstellen:

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

Hoffentlich hilft dies jedem, wahrscheinlich jemandem, der versucht, Bash-Skripte zu erstellen, um CloudFront-Einträge in AWS ungültig zu machen (wie ich!) (Ich habe es noch nicht getestet, aber ich denke, dies ist die Ursache für mein Bash-Skript funktioniert nicht und mein PHP funktioniert ...)

Wouter Thielen
quelle