HMAC-SHA1 dans bash

95

Existe-t-il un script bash pour générer un HMAC-SHA1hachage?

Je recherche quelque chose d'équivalent au code PHP suivant:

hash_hmac("sha1", "value", "key");
marque
la source

Réponses:

185

Je me rends compte que ce n'est pas exactement ce que vous demandez, mais il ne sert à rien de réinventer la roue et d'écrire une version bash.

Vous pouvez simplement utiliser la opensslcommande pour générer le hachage dans votre script.

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

Ou simplement:

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

N'oubliez pas d'utiliser -navec, echosinon un caractère de saut de ligne est ajouté à la chaîne et cela change vos données et le hachage.

Cette commande provient du package OpenSSL qui devrait déjà être installé (ou facilement installé) dans votre choix de Linux / Unix, Cygwin et autres.

Notez que les anciennes versions de openssl(comme celle livrée avec RHEL4) peuvent ne pas fournir cette -hmacoption.


Comme solution alternative, mais principalement pour prouver que les résultats sont les mêmes, nous pouvons également appeler PHP hmac_sha1()depuis la ligne de commande:

[me@home]$ echo '<?= hash_hmac("sha1", "value", "key") ?>' | php
57443a4c052350a44638835d64fd66822f813319
Shawn Chin
la source
Les implémentations d'OpenSSL sont très lentes. Si vous avez besoin de le faire de temps en temps, c'est bien, mais si vous essayez de calculer des quantités massives de hachages, vous voulez étudier différentes avenues.
Marcin le
1
@Marcin: pouvez-vous citer une source avec ça?
sehe
6
J'ai eu la même question avec HMAC-SHA256. La même solution, mais sha1est remplacée par sha256:-)
mogsie
1
Oui, vous pouvez, mais faites attention aux sauts de ligne dans votre fichier, car cela serait également considéré comme faisant partie de la valeur.
Shawn Chin
1
@ShawnChin, dans cet exemple, quel est l'encodage / format de la clé? Doit-il s'agir d'un encodage base64 comme une clé privée créée avec openssl genrsa? De plus, le lien de documentation openssl donne un 404.
Carlos Macasaet
40

Voici une fonction bash qui fonctionne comme hash_hmacdepuis PHP:

#!/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
la source
C'est une belle façon de conclure. +1
Shawn Chin le
+1 car contrairement à la réponse sélectionnée, celle-ci répond à la question posée. (Bien que les deux soient utiles.)
Alexx Roche
mais, comment passez-vous l'argument 'data' au script s'il s'agit de plusieurs lignes? Comme un corps xml ou json sans perdre l'indentation.
HyperioN
@HyperioN si vous avez vos données JSON dans un fichier vous pouvez simplement faire ceci: hash_hmac "sha1" "$(cat your-json-file)" "key". Sinon, vous pouvez simplement diriger votre fichier openssl dgstsans utiliser cette hash_hmacfonction.
Martin
9

Merci pour la fonction hash_hmac! Mais ce n'était pas suffisant pour ma candidature. Au cas où quelqu'un se poserait la question, j'ai dû re-hacher des trucs plusieurs fois en utilisant une clé qui était le résultat du hachage précédent, et donc une entrée binaire. (La signature d'authentification Amazon AWS est créée comme ceci.)

Donc, ce dont j'avais besoin était un moyen de fournir la clé binaire d'une manière qui ne briserait pas l'algorithme. Ensuite, j'ai trouvé ceci: http://openssl.6102.n7.nabble.com/command-line-hmac-with-key-in-hex-td6754.html

La réponse de Stephen Henson nécessite que la fonction hash_hmac renvoie la valeur au format hexadécimal. Il doit donc faire écho à ce qui suit:

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

Ensuite, le prochain appel devra fournir la clé sous forme d'hexit:

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

Espérons que cela aide n'importe qui, probablement quelqu'un qui essaie de créer des scripts bash pour invalider les entrées CloudFront sur AWS (comme moi!) (Je ne l'ai pas encore testé, mais je pense que c'est la raison pour laquelle mon script bash ne fonctionne pas, et mon PHP fonctionne ...)

Wouter Thielen
la source
-2

Pour ceux qui aiment explorer plus JWT sur la ligne de commande: cool script jwt bash

truthadjustr
la source