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.
salt+'-'+secret
and the salt precedes the token in plain text. IIUC brute forcing a hash(secret) would require roughly 2¹⁶⁰ operations. But a bit more than half the input is not kept secret, so would brute forcing takes √2¹⁶⁰=2⁸⁰ operations? This answer suggests that 80b of entropy is not sufficient. – Mike Samuel Nov 02 '17 at 14:27