We need to generate tamper-resistant URLs to access a service, which are then shared with the end-user. The URLs don't contain any confidential data, but we need to ensure that they have not been tampered with since they were generated. It's up to the end-user to keep these confidential.

It seems like a MAC (like HMACSha256) would be appropriate for authenticating the URLs. I'd also like to include a salt and timestamp to make the MAC key less guessable, and so that the signed URLs can naturally expire.

I was thinking that PBKDF2 might be a good way to generate the MAC key, e.g.:

pepper = "xyzzy"
importantFullUrl = "https://....."

salt = secureRandomBits(256)
url = importantFullUrl + "&ts=987654321&salt=" + base62(salt)

signingKey = PBKDF2(pepper, salt, 10000 /*iterations*/, 256 /*bits*/)
mac = hmacSha256(url, signingKey)
signedUrl = url + "&sig=" + base62(mac)

An alternate approach I've seen skips the PBKDF2 step, and just generates the MAC based on the url and pepper values above, i.e.:

mac = hmacSha256(url, pepper)

Does one approach offer significantly more security benefits over the other? Given the URLs will time out after a period (say, 24-48 hours), does it matter in this case? How do I pick a suitable iteration count for a given timeout?

There's an approach described in this question that involves a user-provided password. Users to our service are authenticated using a different mechanism, and do not explicitly have a password. This is also not for a web service, and all of these signed URLs will be generated server-side, and checked again server-side.

  • 2
    PBKDF2 is only useful if the input is a low entropy secret, typically a password. If you have a good secret, you should use a cheap KDF like HKDF. Dec 8, 2013 at 14:58

1 Answer 1


Cryptography should only be used when there is no other option (SSL/TLS is a good example where cryptography is required). An HMAC always introduces the possibility of the trivial attack (brute force). Further more, an HMAC can also be a waste of computation effort, when compared to other solutions such as a simple Cryptographic Nonce used to reference the data.

PBKDF2 is used to stretch low entropy input, such as human generated passwords, to be used as cryptographic keys. In order for PBKDF2 to be useful it will consume significant computational effort to produce the resulting hash. An application exposing this kind of functionality is vulnerable to an Algorithmic Complexity Attack (ACA), and this would be a very serious vulnerability if this was finical software, because DoS attacks result monetary damages.

PBKDF2 is a useful, especially for passwords, however by exposing this function to an attacker without any form of rate-limiting, creates a potential DoS condition. SHA256 is just fine for use as an HMAC, in fact SHA1 would be a better choice for a web application because its faster and the prefixing attacks against SHA1 do not weaken the resulting HMAC. The secret key is what is important, and you still have to worry about offline brute-force attacks. But that can be addressed by making the secret key 128 bytes long, which solves that problem for the life our solar system (with some comfort room!).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .