Explanation of -hmac flag in open SSL

5

2

I came across the following command for unix on binance which I was trying to unpack. See here: https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md

(Section: SIGNED Endpoint Examples for POST /api/v1/order)

openssl dgst -sha256 -hmac

What I understand is it is a call to the openssl command to produce a digest, the digest will be of the sha256 variety as agreed on by standard specs. What I don't understand is the -hmac flag. What is it and what does it do down to a mathematical level?

My Attempt at Solving the Problem:

I did a google search with openssl -hmac and openssl dgst -hmac but the top 10 results were of not avail to me. So I imagine more experienced users would be better to ask.

Updates:

The flag isnt mentioned in these docs: https://www.mkssoftware.com/docs/man1/openssl_dgst.1.asp and so I'm starting to believe it may have no cryptographic purpose. Although i'm right now not sure.

I found what looks similar to the flag mentioned in This Question: https://stackoverflow.com/questions/7285059/hmac-sha1-in-bash

frogeyedpeas

Posted 2018-04-07T00:54:31.470

Reputation: 187

MKS appears to be way out of date, but the website of the OpenSSL project shows this option and the OpenSSL-released man pages have done so for many years.

– dave_thompson_085 – 2018-04-07T06:47:01.263

@dave_thompson_085 I've found an interesting post by jww on StackOverflow and updated my answer with it. The answer is surprising to say the least. – Maarten Bodewes – 2018-04-07T10:37:36.680

Answers

5

HMAC is also called a keyed hash. So you can only generate the same hash during verification if you have the same key used during signature generation. The result of the MAC is called an authentication tag.

HMAC is a special construct that uses two calls to the hash - in your case SHA-256 - that is used internally, and it doesn't use any other cryptographic primitives. It could therefore be seen as a specific mode of the hash itself. Hence the inclusion in dgst.

Missing from your code is the key data, which is of course required to create a keyed hash. This should be presented after -hmac. Unfortunately openssl requires a binary format of the key. For more info see this old conversation on the OpenSSL mailing list.

EDIT #1: Digging a bit deeper, if you want to specify the key as hexadecimals you could use a line like this:

echo -n "Hello world!" | openssl dgst -sha256 -mac hmac -macopt hexkey:01020304

The output of the function is the output of the second run of the hash, so it is indistinguishable from just SHA-256 if you just look at the size of the hash / HMAC result. Of course the contents will be completely different from just hashing the data (or key and data concatenated).


EDIT #2: However, you haven't specified a key, so actually HMAC is skipped and SHA-256 is used. This has been flagged as a bug, see here

Maarten Bodewes

Posted 2018-04-07T00:54:31.470

Reputation: 1 183

1In this API (following the link) they use an ASCII form key, ( a long base64 string) which is then used as an argument after -hmac. If you wanted to use binary keys, you'd have to convert them to hex-strings (as in the enc -K option) and use an alternative form of the command openssl dgst -sha256 -mac HMAC -macopt hexkey:ABCDEF0102 e.g. – Henno – 2018-04-07T07:29:58.560

Of course, entropy-wise it doesn't matter if we use an ASCII-fied key NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j or the equivalent 48 raw bytes. It's common practice in such API-calls to base64 everything so that string methods (or arguments) just work. HTTP prefers ASCII too (for the API keys in headers, etc.) – Henno – 2018-04-07T07:37:03.840

Thanks for the comments Henno. Took some time for me to validate. Posted from the train, it was a bit hard to type the commands. – Maarten Bodewes – 2018-04-07T11:27:38.100

1If someone is using this command to validate libcrypto code, don't forget that if you have const unsigned char data[] = "Hello world!" then the command should have echo -ne "Hello world!\0" with the explicit null terminator. – Daniel – 2019-10-11T16:57:44.837