HMAC-SHA1 in bash


95

Esiste uno script bash per generare un HMAC-SHA1hash?

Sto cercando qualcosa di equivalente al seguente codice PHP:

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

Risposte:


185

Mi rendo conto che questo non è esattamente quello che stai chiedendo, ma non ha senso reinventare la ruota e scrivere una versione bash.

Puoi semplicemente usare il opensslcomando per generare l'hash all'interno del tuo script.

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

O semplicemente:

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

Ricorda di usare -ncon echoaltrimenti un carattere di interruzione di riga viene aggiunto alla stringa e questo cambia i tuoi dati e l'hash.

Quel comando proviene dal pacchetto OpenSSL che dovrebbe essere già installato (o installato facilmente) nella tua scelta di Linux / Unix, Cygwin e simili.

Tieni presente che le versioni precedenti di openssl(come quella fornita con RHEL4) potrebbero non fornire l' -hmacopzione.


Come soluzione alternativa, ma principalmente per dimostrare che i risultati sono gli stessi, possiamo anche chiamare PHP hmac_sha1()dalla riga di comando:

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

Le implementazioni di OpenSSL sono molto lente. Se devi farlo occasionalmente va bene, ma se stai cercando di calcolare enormi quantità di hash, vuoi indagare su strade diverse.
Marcin

1
@ Marcin: puoi citare una fonte con quello?
guarda il

6
Ho avuto la stessa domanda con HMAC-SHA256. La stessa soluzione, ma sha1viene sostituita con sha256:-)
mogsie

1
Sì, puoi, ma fai attenzione alle interruzioni di riga all'interno del tuo file poiché anche questo sarebbe considerato parte del valore.
Shawn Chin

1
@ShawnChin, in questo esempio, qual è la codifica / formato della chiave? Dovrebbe essere una codifica base64 come una chiave privata creata utilizzando openssl genrsa? Inoltre, il collegamento alla documentazione di openssl risulta in un 404.
Carlos Macasaet

40

Ecco una funzione bash che funziona come hash_hmacda 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"

È un bel modo per concludere. +1
Shawn Chin

+1 perché a differenza della risposta selezionata, questa risponde alla domanda posta. (Anche se entrambi sono utili.)
Alexx Roche

ma come si passa l'argomento 'data' allo script se è su più righe? Come un corpo xml o json senza perdere il rientro.
HyperioN

@HyperioN se avete i dati JSON in un file si può semplicemente fare questo: hash_hmac "sha1" "$(cat your-json-file)" "key". In alternativa puoi semplicemente reindirizzare il tuo file openssl dgstsenza usare questa hash_hmacfunzione.
Martin

9

Grazie per la funzione hash_hmac! Ma non era abbastanza per la mia domanda. Nel caso qualcuno se lo chiedesse, ho dovuto ripetere l'hashing più volte usando una chiave che era il risultato dell'hash precedente, e quindi è un input binario. (La firma di autenticazione di Amazon AWS viene creata in questo modo.)

Quindi quello di cui avevo bisogno era un modo per fornire la chiave binaria in un modo che non rompesse l'algoritmo. Poi ho trovato questo: http://openssl.6102.n7.nabble.com/command-line-hmac-with-key-in-hex-td6754.html

La risposta di Stephen Henson richiede che la funzione hash_hmac restituisca il valore in formato esadecimale. Quindi deve echeggiare quanto segue:

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

Quindi la chiamata successiva dovrebbe fornire la chiave come hexit:

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

Spero che questo aiuti chiunque, probabilmente qualcuno che sta cercando di creare script bash per invalidare le voci CloudFront su AWS (come me!) (Non l'ho ancora testato, ma penso che questa sia la causa del motivo per cui il mio script bash non funziona e il mio PHP funziona ...)


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.