69

I'm creating HTTP REST service which will be available over tls only.

For authentication purposes I plan to generate JWT token for every user using HMAC HS256. I need a secret key for HMAC.

What are the requirements for secret key?

Do I need a long string of random characters? Or fixed-length string? Or what?

wdmssk
  • 31
  • 1
  • 4
ivstas
  • 793
  • 1
  • 6
  • 6

4 Answers4

53

I've added my answer here as I feel the existing ones don't directly address your question enough for my liking.

Let's look at RFC 4868 (regarding IPSec, however it covers the HMAC-SHA256 function you intend to use - em mine):

Block size: the size of the data block the underlying hash algorithm operates upon. For SHA-256, this is 512 bits, for SHA-384 and SHA-512, this is 1024 bits.

Output length: the size of the hash value produced by the underlying hash algorithm. For SHA-256, this is 256 bits, for SHA-384 this is 384 bits, and for SHA-512, this is 512 bits.

As WhiteWinterWolf notes, longer than B (block size) is discouraged because the value must be hashed using SHA-256 first (i.e. 512 bits in this case) and less than L (output length) is discouraged (256 bits in this case). However, a 256 bit key is overkill as anything that is 128bits or greater cannot be brute forced in anyone's current lifetime, even if every computer in the world was working on cracking it.

Therefore I'd recommend a 128 bit key, generated with a cryptographically secure pseudo random number generator (CSPRNG). If you want to store this as text then a 128 bit key can be represented by generating a random 32 character length hex string, or alternatively you could generate 16 random bytes and then run them through a base64 function.

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
  • 2
    Just adding a reference toward the [OWASP recommendations regarding session ID length and comments about session ID entropy](https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Session_ID_Length) which provides more explanation about the choice of 128 bits. – WhiteWinterWolf Jan 09 '16 at 10:51
  • 1
    *12* bytes, base64 encoded, give 128 bits. Every 6 bits (2^6 = 64) is encoded as an 8-bit char, so we have 12/6*8*8 = 128. – Aryeh Leib Taurog Mar 02 '16 at 14:30
  • 9
    @AryehLeibTaurog: 12 bytes gives a size of 128 bits when base64 encoded, however the underlying entropy would only be 96 bits. This is because not every bit combination is valid in the resultant encoding. – SilverlightFox Mar 02 '16 at 15:38
  • 1
    It's inherently dated to estimate the amount of time it takes to brute force anything, even though Moore's law has been slowing down. – Ekevoo Jul 05 '17 at 22:09
  • @eke Not sure what you're referring to as no time was estimated at all in my answer or the following comments. – SilverlightFox Jul 06 '17 at 06:31
  • @eke unless you're referring to 'lifetime" as an estimate :D? See here https://securityintelligence.com/moores-law-and-cryptography-for-business-do-we-need-a-larger-key-space/ – SilverlightFox Jul 06 '17 at 18:49
  • @SilverlightFox That article wasn't very persuasive to me (same old and dated assumptions), but this video did convince me: https://www.youtube.com/watch?v=S9JGmA5_unY – Ekevoo Jul 25 '17 at 15:55
  • 3
    It should be 256 as JWA states. – Silver Sep 12 '17 at 08:28
23

According to RFC 7518 - JSON Web Algorithms (JWA):

A key of the same size as the hash output (for instance, 256 bits for "HS256") or larger MUST be used with this algorithm. (This requirement is based on Section 5.3.4 (Security Effect of the HMAC Key) of NIST SP 800-117 (sic) [NIST.800-107], which states that the effective security strength is the minimum of the security strength of the key and two times the size of the internal hash value.)

So in the case of JWT, you MUST use a key of at least 256 bits with HS256.

jordanbtucker
  • 330
  • 2
  • 5
12

The RFC 2104 defining HMAC functions answers this question:

The key for HMAC can be of any length (keys longer than B bytes are first hashed using H). However, less than L bytes is strongly discouraged as it would decrease the security strength of the function. Keys longer than L bytes are acceptable but the extra length would not significantly increase the function strength. (A longer key may be advisable if the randomness of the key is considered weak.)

Keys need to be chosen at random (or using a cryptographically strong pseudo-random generator seeded with a random seed), and periodically refreshed. (Current attacks do not indicate a specific recommended frequency for key changes as these attacks are practically infeasible. However, periodic key refreshment is a fundamental security practice that helps against potential weaknesses of the function and keys, and limits the damage of an exposed key.)

For information, the following notation is used in this excerpt:

We assume H to be a cryptographic hash function where data is hashed by iterating a basic compression function on blocks of data. We denote by B the byte-length of such blocks (B=64 for all the above mentioned examples of hash functions), and by L the byte-length of hash outputs (L=16 for MD5, L=20 for SHA-1).

WhiteWinterWolf
  • 19,082
  • 4
  • 58
  • 104
2

EDIT: Wrong answer. Left undeleted to preserve comments thread.


HMAC user-input keys that are longer than the specific hash algorithms blocksize are first shortened. (By running the long keys through the hash. And then using that hash as the actual key.)

SHA256 outputs 256 bit hashes. That's 32 bytes. So I suggest you generate 256 bit HMAC secret keys. (Using a cryptographically secure random generator.) Keys any longer will offer no additional security.

StackzOfZtuff
  • 17,783
  • 1
  • 50
  • 86
  • Did I get it correct: I need to generate random 256 bit sequence (in case of using HMAC with HS256) using cryptographically secure random generator and then use it as key? – ivstas Aug 05 '15 at 11:14
  • 1
    If you want HMAC-SHA256's maximum strength, then yes. – StackzOfZtuff Aug 05 '15 at 11:25
  • 8
    Let's be precise: with SHA-256, the _output_ size is 256 bits, but the _block_ size is 512 bits, so the "shortening" occurs only for keys of more than 512 bits. However, cryptographic keys (for symmetric algorithms like HMAC) longer than 128 bits don't really add security, so there is no actual need to go to a full block-length key. – Tom Leek Aug 05 '15 at 12:16
  • 1
    To be even more precise: you would use a random number generator for a completely new key. It is possible for instance to obtain a key from a Key Derivation Function, possibly using a key agreement protocol. As long as all the allowed keys for your specific size are equally possible to an attacker you're good. – Maarten Bodewes Aug 05 '15 at 13:26
  • 1
    Thanks, Tom, Maarten. I've placed a warning above my former answer. I'm leaving it alive for sake of this comments thread. – StackzOfZtuff Aug 05 '15 at 13:36