4

Does it make sense to use stateless JWT (without persistent storage) over plain SHA256?

Example scenario:

  1. User logs in

  2. User token generated as follows:
    a. JWT.encode(userId, 'secret')
    or
    b. SHA256(userId + 'secret')

  3. Client app sends request with userId and token

  4. Request is verified via:
    a. JWT.decode(token, 'secret'), then checking that resulting JWT.userId compared to request userId
    or
    b. SHA256(userId + 'secret'), then checking that resulting hash compared to request token

JWT allows token expiration, however beyond that I don't see any benefit?

SyBer
  • 143
  • 1
  • 5

1 Answers1

3

Does it make sense to use stateless JWT (without persistent storage) over plain SHA256?

What you're essentially doing with "plain SHA256" is signing the data and sending the data + signature separately. JWT encodes both the signature and the data together, but in both cases you're basically signing the data sending the signature + data.

In essence both a and b are doing fundamentally the same thing.

Having said that, there's several reasons why JWT is superior to the method you've proposed.

Use of HMAC

HMAC addresses some weaknesses of simply hashing data + a secret key:

For example, one might assume the same security that HMAC provides could be achieved with MAC = H(key ∥ message). However, this method suffers from a serious flaw: with most hash functions, it is easy to append data to the message without knowing the key and obtain another valid MAC ("length-extension attack"). The alternative, appending the key using MAC = H(message ∥ key), suffers from the problem that an attacker who can find a collision in the (unkeyed) hash function has a collision in the MAC (as two messages m1 and m2 yielding the same hash will provide the same start condition to the hash function before the appended key is hashed, hence the final hash will be the same).

http://en.wikipedia.org/wiki/Hash-based_message_authentication_code

Support for public key cryptography

To generate the MAC using SHA256 alone it is necessary for both parties to know the plain-text secret.

This is difficult to maintain securely as:

a. The secret must be stored and recoverable in plain-text format, therefore neither side can store the secret as a salted hash. This is particularly a problem for the verifying / server side in a web application who might need to store secrets for thousands of users.

b. The parties need to communicate the shared secret somehow

JWT supports RSA which is a public-key encryption system. Therefore the signing party needs to secure their private key, but the verifying party (ie. usually the server) only has to know the public key. The public key is public information so it doesn't need to be stored as securely.

Public keys are also easier to share, because it is not necessary to communicate anything that can be used to sign messages (although an attacker could substitute it for their own public key), as opposed to the method without RSA where the secret must be communicated.

thexacre
  • 8,444
  • 3
  • 24
  • 35
  • Thanks for the detailed reply. I was familiar with HMAC before, but the reply has clicked it into the context. Just for clarification, SHA256('secret2' + SHA256(userId + 'secret1')) will answer on the first comment, as long as secret 1 and 2 are far enough one from another, correct? – SyBer May 08 '15 at 02:59
  • Yes; Hamming distance is the rationale behind the choice of opad / ipad in the HMAC algorithm. Why reinvent the wheel when you can just use HMAC? You can also protect against length-extension attacks by truncating the output (i.e. discarding hash state). See questions https://crypto.stackexchange.com/questions/20695/hmac-ipad-and-opad-choice and https://crypto.stackexchange.com/questions/3005/what-do-the-magic-numbers-0x5c-and-0x36-in-the-opad-ipad-calc-in-hmac-do – Arran Schlosberg May 08 '15 at 09:18