HMAC-SHA1 em bash

95

Existe um script bash para gerar um HMAC-SHA1hash?

Estou procurando algo equivalente ao seguinte código PHP:

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

Respostas:

185

Sei que não é exatamente isso que você está pedindo, mas não adianta reinventar a roda e escrever uma versão do bash.

Você pode simplesmente usar o opensslcomando para gerar o hash em seu script.

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

Ou simplesmente:

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

Lembre-se de usar -ncom, echoou então, um caractere de quebra de linha é anexado à string e isso altera seus dados e o hash.

Esse comando vem do pacote OpenSSL que já deve estar instalado (ou facilmente instalado) em sua escolha de Linux / Unix, Cygwin e similares.

Observe que as versões mais antigas do openssl(como a fornecida com o RHEL4) podem não oferecer a -hmacopção.


Como solução alternativa, mas principalmente para provar que os resultados são os mesmos, também podemos chamar PHP's hmac_sha1()da linha de comando:

[me@home]$ echo '<?= hash_hmac("sha1", "value", "key") ?>' | php
57443a4c052350a44638835d64fd66822f813319
Shawn Chin
fonte
As implementações do OpenSSL são muito lentas. Se você precisar fazer isso ocasionalmente, tudo bem, mas se estiver tentando calcular grandes quantidades de hashes, você deve investigar diferentes caminhos.
Marcin,
1
@Marcin: você pode citar uma fonte com isso?
ver
6
Eu tive a mesma pergunta com o HMAC-SHA256. A mesma solução, mas sha1foi substituída por sha256:-)
mogsie
1
Sim, você pode, mas tome cuidado com as quebras de linha em seu arquivo, pois isso também seria considerado parte do valor.
Shawn Chin de
1
@ShawnChin, neste exemplo, qual é a codificação / formato da chave? Deve ser uma codificação base64 como uma chave privada criada usando openssl genrsa? Além disso, o link de documentação do openssl resulta em um 404.
Carlos Macasaet
40

Aqui está uma função bash que funciona como hash_hmacPHP:

#!/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
fonte
Essa é uma boa maneira de encerrar. +1
Shawn Chin
+1 porque, ao contrário da resposta selecionada, esta responde à pergunta feita. (Embora ambos sejam úteis.)
Alexx Roche
mas, como você passa o argumento 'dados' para o script se ele for multilinha? Como um corpo xml ou json sem perder a indentação.
HyperioN
@HyperioN se você tiver seus dados JSON em um arquivo que você pode simplesmente fazer isso: hash_hmac "sha1" "$(cat your-json-file)" "key". Como alternativa, você pode simplesmente canalizar seu arquivo openssl dgstsem usar esta hash_hmacfunção.
Martin
9

Obrigado pela função hash_hmac! Mas não foi o suficiente para minha aplicação. Caso alguém esteja se perguntando, eu tive que refazer o hash várias vezes usando uma chave que era o resultado do hash anterior e, portanto, é uma entrada binária. (A assinatura de autenticação Amazon AWS é criada assim.)

Então, o que eu precisava era uma maneira de fornecer a chave binária de alguma forma que não quebrasse o algoritmo. Então eu encontrei isto: http://openssl.6102.n7.nabble.com/command-line-hmac-with-key-in-hex-td6754.html

A resposta de Stephen Henson requer que a função hash_hmac retorne o valor em formato hexadecimal. Portanto, ele precisa ecoar o seguinte:

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

Então, a próxima chamada precisaria fornecer a chave como um hexit:

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

Espero que isso ajude alguém, provavelmente alguém que está tentando criar scripts bash para invalidar entradas do CloudFront no AWS (como eu!) (Eu não testei ainda, mas acho que é isso que é a causa de porque meu script bash não funciona, e meu PHP funciona ...)

Wouter Thielen
fonte
-2

Para aqueles que gostam de explorar mais JWT na linha de comando: cool jwt bash script

Truthadjustr
fonte