shankardevy
shankardevy

Reputation: 4370

Problem in verifying hmac signature generated in Elixir and Python with Hashcorp vault

This is what I'm trying to do:

  1. I'm creating a transit key in Hashicorp vault and sending the hmac_key of this transit key to my elixir/ python client.

  2. The intention is that the elixir/python client will use this hmac_key to generate a hmac digest and send the data with this digest to my application.

  3. My application will then send the same data and digest to vault to verify if the digest is valid.

Generating Transit key in Vault

vault write transit/keys/key1 allow_plaintext_backup=true exportable=true

Exporting the HMAC KEY to send to client

vault read transit/export/hmac-key/key1                                  

Key     Value
---     -----
keys    map[1:Ui9+az/p3GdAb1BZ3SJwPkauw2nyT9vm5EE2rzG1OMc=]
name    key1
type    aes256-gcm96

Generating HMAC in Elixir

I use the HMAC KEY from vault to generate hmac of my data

iex> secret = "Ui9+az/p3GdAb1BZ3SJwPkauw2nyT9vm5EE2rzG1OMc="
iex> data = "hello-world"
iex> :crypto.hmac(:sha256, Base.decode64!(secret), data) |> Base.encode64

"sEDTm/luPTmJ3AveP+wu8B+iXzJ89Rx43QxiWfT9ysM="

Trying to verify the hmac using Vault

vault write transit/verify/key1/sha2-256 input=$(base64 <<< "hello-world") hmac="vault:v1:sEDTm/luPTmJ3AveP+wu8B+iXzJ89Rx43QxiWfT9ysM="
Key      Value
---      -----
valid    false

This returns false when I expect it to return true.

Using Vault to generate HMAC

vault write transit/hmac/key1/sha2-256 input=$(base64 <<< "hello-world") 

Key     Value
---     -----
hmac    vault:v1:yuKdushC10olNUHfkIj3QRHnVGvQl80DUtsuKHSnfgo=

Clearly the Vault generated hmac yuKdushC10olNUHfkIj3QRHnVGvQl80DUtsuKHSnfgo= is different from the Elixir generated hmac ZfF4qLcMfCQ1Ns6xtUiV0grE98S9E6ywaALF2mWGKkI= using the same key.

Generating the HMAC in Python

import hmac
import hashlib
import base64
secret = base64.b64decode("Ui9+az/p3GdAb1BZ3SJwPkauw2nyT9vm5EE2rzG1OMc=")
data = b'hello-world'
signature = hmac.new(secret, data, digestmod=hashlib.sha256)
print(base64.b64encode(signature.digest()))

# b'sEDTm/luPTmJ3AveP+wu8B+iXzJ89Rx43QxiWfT9ysM='

The HMAC from Python and Elixir are the same for the given key. However, the HMAC from Vault is not. What am I doing wrong here? Is vault using a different HMAC KEY for generating the HMAC? I triple checked that I'm using the exported HMAC KEY in my Elixir and Python script.

Any help is appreciated.

Thanks

Upvotes: 2

Views: 606

Answers (1)

Dogbert
Dogbert

Reputation: 222198

<<< adds a newline to the end of the string. If I manually add the \n to the data in Elixir, I get the same hash as hashicorp-vault:

iex(1)> secret = "Ui9+az/p3GdAb1BZ3SJwPkauw2nyT9vm5EE2rzG1OMc="
"Ui9+az/p3GdAb1BZ3SJwPkauw2nyT9vm5EE2rzG1OMc="
iex(2)> data = "hello-world"
"hello-world"
iex(3)> :crypto.hmac(:sha256, Base.decode64!(secret), data <> "\n") |> Base.encode64
"yuKdushC10olNUHfkIj3QRHnVGvQl80DUtsuKHSnfgo="

You can remove the newline in bash using echo -n:

input=$(base64 <(echo -n "hello-world"))

Upvotes: 3

Related Questions