0

I ran across some CSRF code that does:

Tokens.prototype._tokenize = function tokenize (secret, salt) {
  return salt + '-' + hash(salt + '-' + secret)
}

where hash seems to be a SHA1 digest modified to fit in a multipart/form-data body without extra encoding:

function hash (str) {
  return crypto
    .createHash('sha1')
    .update(str, 'ascii')
    .digest('base64')
    .replace(PLUS_GLOBAL_REGEXP, '-')
    .replace(SLASH_GLOBAL_REGEXP, '_')
    .replace(EQUAL_GLOBAL_REGEXP, '')
}

IIUC, the use of hash doesn't prevent forging. Does this provide much over just using a closely held nonce?

Does hash make it particularly difficult to derive the input? Since secret is not encrypted, this seems to assume that either

  • secret need not be secret or
  • the token is closely held, which should be the case for a CSRF token.
Mike Samuel
  • 103
  • 3

2 Answers2

1

the use of hash doesn't prevent forging. Does this provide much over just using a closely held nonce?

on the contrary, the use of hash described should prevent forging assuming the secret is kept .. well.. secret

Does hash make it particularly difficult to derive the input? Since secret is not encrypted, this seems to assume that either

Indeed, it should be very hard to derive input (secret) from its hash. That's one of the mandatory properties of a hash function. The secret should stay secret on the server side (not revealed to the client)

secret need not be secret or the token is closely held, which should be the case for a CSRF token.

if the secret is revealed, the client could forge a new valid CSRF token

gusto2
  • 1,194
  • 7
  • 14
1

This looks like a straightforward application for a MAC. Let's summarize the security property of MACs: if the honest party chooses the key at random and keeps it secret, it should be impossible in practice for an adversary to forge a tag for any input of their choice. This property is known as existential unforgeability under chosen message attack, a.k.a. EU-CMA. So HMAC is just a perfect tool for this task, and should be preferred over homebrew solutions like the code you show.

Since secret is not encrypted [...]

You seem to have some misconception here. secret needs to be, well, secret—i.e., known to the honest parties but unknown to the adversaries. That has nothing to do with whether it's encrypted or not.

I don't understand what you mean by a "closely held nonce" but I suspect by "closely held" you actually mean secret.

Luis Casillas
  • 14,703
  • 2
  • 33
  • 53