5

I'm not really strong at cryptography, so there is my question.

Our application — forum — sends our users notifications of new messages, if they opted for it. In the email there should be a link to unsubscribe from this messages. Now, I want that link to work, even if the user is not currently authenticated at our service (no cookie).

To do that, I decided to just sign the request with SHA1, like this:

http://example.com/unsubscribe?u=234&s=52342&h=0b071440146545eaf3f00ef9cdeb1d47d006dfff

Here u is the ID of the user, who wants to unsubscribe, s is some random salt, h is the secure hash calculated by concatenating the name of the action (unsubscribe), parameters and their values (u=234s=52342) and some secret string, specified in the configuration of our service and calculating SHA1 hash of the resulting string:

sha1('unsubscribeu=234s=52342supersecret')

My question is about this parameter s, which is generated randomly every time. Does it add to the security here or not? Is it really needed?

If I go with the encryption instead, does it make sense to add this kind of salt to the data being encrypted?

This is more of a theoretical question, since it is very unlikely that someone would want to guess that "supersecret" at our service just to prank-unsubscribe a bunch of users, but still interesting.

Maxim Sloyko
  • 15,176
  • 9
  • 43
  • 49

3 Answers3

3

The main use for a salt is to prevent comparison of various hashed values for analysis; for example, to see if any two users have the same passwords by comparing the hash values of their passwords. If random salts are added, that comparison is not possible (unless both the passwords and the salts are equal - which should not happen because a salt should be random)

In your case, I don't think there is any benefit from the salt value unless you also store those salts on the server end and 'expire' them once used, so that a certain unsubscribe link - with its salt value - could not be 'replayed' again later.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • No, I don't store them on the server, I just add them so that the link itself would be different in different emails received by the user... Not quite sure if this is good or not. – Maxim Sloyko Dec 29 '10 at 09:30
  • Having and validating the hash that includes the user's ID means that no one can craft a working unsubscribe link already. Having your 'secret' value included in that means someone can't do that even if they know every other detail involved. The salt does not add to those (though it does not hurt, either) – Andrew Barber Dec 29 '10 at 09:37
0

I'm in no means a security expert but I think I could leave my 2 cents.

The "S" parameter (i.e. "salt" as you call it) is a security token and it's your primary security measure. The hash is there to make manipulating URL parameters harder (or even impossible), so that the end user is not able to fire actions with another token on a similar call.

You should probably store the token along with the unsubscribe user request and check for equality on a subsequent confirmation call (validating user unsubscribe action). After checking the hash of the URL parameters, of course (validating if the request is not manipulated)

Mike Minicki
  • 8,216
  • 11
  • 39
  • 43
  • The idea is for unsubscription to be as easy as possible, so the user does not need to validate the unsubscribe action. She just clicks the link and she's unsubscribed. I just need to properly authenticate her. – Maxim Sloyko Dec 29 '10 at 09:33
  • @Michał Minicki - a request can not currently be manipulated even if the salt is removed, because no one knows the 'secret' value, which is part of where the hash was generated from. – Andrew Barber Dec 29 '10 at 09:39
  • @maksymko - if you remove the salt, hash will be the same every time (user id and your server side secret is constant). So if the user subscribes again, everybody in possession of the previous URL could unsubscribe them again. It's only a matter of how secure you plan it to be. – Mike Minicki Dec 29 '10 at 13:21
  • 2
    @maksymko - as a side node. You're not authenticating the user here; you're authenticating the source of your link. Authentication is a process of identity verification and you actually can't be sure if it's the user 234 who clicked the link. What you're sure about is that the link was created on your site (via params hash with server secret) and that's all. – Mike Minicki Dec 29 '10 at 13:35
  • @Michał Minicki +1 for noting exactly what is being secured. – Andrew Barber Dec 30 '10 at 00:47
0

What you want is not a salt, but rather a nonce. By using a nonce, and recording the fact that it's been used, you can limit the risk the exposure of the secret URL would incur.

Also, instead of concatenating your secret with the hashed string, use an HMAC.

Nick Johnson
  • 100,655
  • 16
  • 128
  • 198