0
$\begingroup$

I know how standard HMAC(key,msg) function works, and I want to write a Delphi port of HMAC class that implements Update function. The problem is that I don't understand how this Update function works (for example of Update function, see SSL definition here: https://www.openssl.org/docs/crypto/hmac.html).

If I understand this correctly, these two pieces of pseudocode should return the same HMAC (e.g. Result1 = Result2):

Code 1: HMAC.Init; HMAC.Update('key','abc'); HMAC.Update('key','def'); Result1 = HMAC.Digest;

Code 2: HMAC.Init; HMAC.Update('key','abcdef'); Result2 = HMAC.Digest;

I have found Python implementation here: https://hg.python.org/cpython/file/2.7/Lib/hmac.py but I have no knowledge of Python (I am Delphi programmer) and I don't undesrtand it. Could somebody explain it to me, or, possible provide an example of pseudocode/Delphi?

EDIT: Probably I should have given some more details about the reason I have asked this question. Basically, I need to calculate HMAC(key,msg) where msg is a content of a stream/file, which can be big - and therefore its contents can't be passed to HMAC function at once. Therefore I need to read blocks of the stream and continuously update the HMAC message, so that after whole stream/file was processed, HMAC digest contains HMAC of the whole stream.

$\endgroup$
  • $\begingroup$ I don't see that it makes sense to pass a key to HMAC.Update, and neither of your references does. Equivalent uses HMAC.Init('key'); HMAC.Update('abc'); HMAC.Update('def'); Result1 = HMAC.Digest and HMAC.Init('key'); HMAC.Update('abcdef'); Result1 = HMAC.Digest seem more logical to me; and then I do not get what you ask. $\endgroup$ – fgrieu Jun 16 '15 at 20:38
  • $\begingroup$ @fgrieu, I quickly followed the OpenSSL link. OpenSSL uses HMAC_Init(CTX,key,...) and HMAC_Update(CTX,data,...) as well as HMAC_Final(CTX,digest,...). Just read _secret_backdoor_key = [] in the python code... Author has humour :) And the python code does indeed only offer key-init in the init-function, so update only accepts messages meaning the above instructions are either invalid or if 'key' is moved to Init, Result1 = Result2 $\endgroup$ – SEJPM Jun 16 '15 at 20:47
  • $\begingroup$ crypto.stackexchange.com/questions/16510/… $\endgroup$ – Richie Frame Jun 16 '15 at 23:56
  • $\begingroup$ Richie, it seems that "progressive hash" is all I needed to search. I kept searching for things like "incremental HMAC" and something like that and could not find too much :-) $\endgroup$ – Acetylator Jun 17 '15 at 14:26
1
$\begingroup$

Let's shortly recall, how HMAC looks like:

$HMAC_K(M):=H((K\oplus opad) || H((K \oplus ipad) || M))$

As you may observe here, the calculation of the outer hash is fully independant of the message.

So the standard approach into implenting "update" functionality is to store the key and go as follows:

Init(Key):
Store the Key in K
Init two Hash-function instances H1 and H2
Feed (K XOR IPAD) into H1
Feed (K XOR OPAD) into H2

Update(Message):
Feed the Message into H1

Final:
Get the digest of H1 and feed it into H2
Output the digest of H2
$\endgroup$
  • $\begingroup$ As I stated, I do not want to use any external libraries, I want to do my own implementation which must, however, produce same results as the reference HMAC implementation. $\endgroup$ – Acetylator Jun 16 '15 at 21:12
  • $\begingroup$ @Acetylator ohh, now I understand your question... I'll update my answer. But be warned: Your hash-function must support the update functionality. $\endgroup$ – SEJPM Jun 16 '15 at 21:19
  • $\begingroup$ @Acetylator, updated the answer. It now describes how to construct update-able HMAC from an updateable hash-function using the three well-known functions: Init(Key), Update(Message) and Final (outputting the digest) $\endgroup$ – SEJPM Jun 16 '15 at 21:26
  • $\begingroup$ This is exactly what I was looking for! Thank you very much! $\endgroup$ – Acetylator Jun 16 '15 at 21:41
  • 1
    $\begingroup$ @Acetylator: Notice that if/when Key is longer that the block size (64 bytes for SHA-1 and SHA-256, 128 bytes for SHA-512), the hash of Key (rather than Key extended to a block when Key is smaller than a block) shall be used as K. $\;$ Independently: some implementations deffer initialization of H2 until Final, instead keeping K (or K XOR OPAD) for this purpose; this avoids multiple active instances of the hash, which typically conserves memory. $\endgroup$ – fgrieu Jun 17 '15 at 9:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.