HMAC-SHA1 en bash

95

¿Existe un script bash para generar un HMAC-SHA1hash?

Estoy buscando algo equivalente al siguiente código PHP:

hash_hmac("sha1", "value", "key");
marca
fuente

Respuestas:

185

Me doy cuenta de que esto no es exactamente lo que estás pidiendo, pero no tiene sentido reinventar la rueda y escribir una versión de bash.

Simplemente puede usar el opensslcomando para generar el hash dentro de su script.

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

O simplemente:

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

Recuerde usar -ncon echoo, de lo contrario, se agrega un carácter de salto de línea a la cadena y eso cambia sus datos y el hash.

Ese comando proviene del paquete OpenSSL que ya debería estar instalado (o instalado fácilmente) en su elección de Linux / Unix, Cygwin y similares.

Tenga en cuenta que es posible que las versiones anteriores de openssl(como la que se envía con RHEL4) no ofrezcan la -hmacopción.


Como solución alternativa, pero principalmente para demostrar que los resultados son los mismos, también podemos llamar a PHP hmac_sha1()desde la línea de comandos:

[me@home]$ echo '<?= hash_hmac("sha1", "value", "key") ?>' | php
57443a4c052350a44638835d64fd66822f813319
Shawn Chin
fuente
Las implementaciones de OpenSSL son muy lentas. Si necesita hacerlo de vez en cuando, está bien, pero si está tratando de calcular cantidades masivas de hashes, desea investigar diferentes vías.
Marcin
1
@Marcin: ¿puedes citar una fuente con eso?
sehe
6
Tuve la misma pregunta con HMAC-SHA256. La misma solución, pero sha1se reemplaza con sha256:-)
mogsie
1
Sí, puede, pero tenga cuidado con los saltos de línea dentro de su archivo, ya que eso también se consideraría parte del valor.
Shawn Chin
1
@ShawnChin, en este ejemplo, ¿cuál es la codificación / formato de la clave? ¿Debería ser una codificación base64 como una clave privada creada usando openssl genrsa? Además, el enlace de documentación de openssl da como resultado un 404.
Carlos Macasaet
40

Aquí hay una función bash que funciona como hash_hmacdesde 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"
Martín
fuente
Esa es una buena manera de terminarlo. +1
Shawn Chin
+1 porque a diferencia de la respuesta seleccionada, esta responde la pregunta formulada. (Aunque ambos son útiles)
Alexx Roche
pero, ¿cómo se pasa el argumento 'datos' al script si es de varias líneas? Como un cuerpo xml o json sin perder la sangría.
HyperioN
@HyperioN si tiene los datos JSON en un archivo que puede simplemente hacer esto: hash_hmac "sha1" "$(cat your-json-file)" "key". Alternativamente, puede canalizar su archivo openssl dgstsin usar esta hash_hmacfunción.
Martin
9

¡Gracias por la función hash_hmac! Pero no fue suficiente para mi aplicación. En caso de que alguien se preguntara, tuve que volver a hacer hash varias veces usando una clave que era el resultado del hash anterior y, por lo tanto, es una entrada binaria. (La firma de autenticación de Amazon AWS se crea así).

Entonces, lo que necesitaba era una forma de proporcionar la clave binaria de alguna manera que no rompiera el algoritmo. Luego encontré esto: http://openssl.6102.n7.nabble.com/command-line-hmac-with-key-in-hex-td6754.html

La respuesta de Stephen Henson requiere que la función hash_hmac devuelva el valor en formato hexadecimal. Por lo que debe hacerse eco de lo siguiente:

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

Luego, la siguiente llamada debería proporcionar la clave como un hexit:

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

Espero que esto ayude a cualquiera, probablemente alguien que esté tratando de crear scripts bash para invalidar entradas de CloudFront en AWS (¡como yo!) (No lo he probado todavía, pero creo que esta es la causa de por qué mi script bash no funciona, y mi PHP uno sí ...)

Wouter Thielen
fuente