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.