Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm adding a click-tracking feature on my website to track click-thrus for my advertisers.

So, on my site, instead of having a direct link, I link to my re-direct page passing the destination url as an argument. This re-direct page then tracks the click thru and then 301 re-directs the user to the correct external url.

I want to prevent 3rd partys from harnessing this system to make it re-direct to arbitrary urls.

I'd like the code that creates the links to:

Create special token using ( destination url + secret )

Then, pass the destination url + special token arguments as query string parameters to my re-direct page in public.

Upon receiving the arguments the re-direct page will do a check:

Given ( destination url + special token + secret ), destination url is either:

  • good - re-direct it to destination
  • bad - do not re-direct it to destination

and it should not be possible for Doctor Evil to:

Create secret using ( known valid destination url + its special token )


Ideally the re-direct page would not have to do any url-specific look-ups on data to validate the parameters - it should just be able to tell from 'the two params given + the secret + the known algorithm'.

I'm not very knowledgeable about encryption so was wondering what kind of method one would use to create and validate the parameters given the shared secret.

I'm sure this is a common technique but I have no idea what its called - thus its difficult to learn more about it.

Any help is appreciated.

share|improve this question

3 Answers 3

up vote 1 down vote accepted

As Jerry wrote, a MAC function is the easiest way to do this.

In PHP there are library functions available for this. I would suggest using HMAC (see hash_hmac() in the PHP manual) using either MD5 or sha256 as the corresponding hashing algorithm (this is the first argument to the function).

If you are interested in further details on Message Authentication Codes or hashing algorithms then I would suggest reading the Wikipedia articles for a good overview.

share|improve this answer
    
Perfect, that's the function I was looking for. Thanks. –  JW01 Sep 22 '11 at 18:04

The obvious way would be to use a Message Authentication Code (MAC -- a heavily overloaded TLA if ever there was one). A MAC is basically a keyed hash algorithm. You keep the key private, and when you add a URL to your system, you give the owner of that URL the hash of their URL using your key. They pass the authentication back along with the URL. When you get it, you re-hash the URL using your key, and verify that it matches what they passed. If it doesn't match, you reject it.

If you don't have code for a MAC easily available, one easy way to produce one from typical primitives is to do an unkeyed hash (e.g. SHA-256) then encrypt the result of that with a normal encryption algorithm (e.g., AES).

You may want to preprocess the URL to allow some minor variations. Just for example, in a typical case where capitalization doesn't matter, you don't want to start rejecting a URL just because somebody changed something like "MyUrl" to "MyURL". As such, you may want (for one possibility) to convert the entire URL to lower case first.

share|improve this answer
    
This is very helpful. Thanks for the speedy reply. I am understanding the first paragraph. But, a bit confused with the second one. Are these two separate techniques? What do you "do an unkeyed hash" of? –  JW01 Sep 21 '11 at 20:57
    
You do an unkeyed hash of the data you want to prevent someone from tampering with. So instead of just passing X, you pass X along with an encrypted hash of X. If someone wants to tamper with X, they need to also tamper with the encrypted hash, which (not knowing the key) they wouldn't know how to do. The most common mechanism for this is called HMAC. (HMAC-SHA1 is probably already available in whatever platform you use.) –  David Schwartz Sep 22 '11 at 5:44
    
Thanks that makes sense to me now. –  JW01 Sep 22 '11 at 18:03

Yes, i've invented a method to do so. Unlike Jerry's MAC solution, I created the authentication code using public/private key encryption. If you create the authentication code with your private key, the validation only requires a public key. That means that even if your server is compromised and the public key would be obtained, it still wouldn't allow third parties to create new signed URLs.

You might want to check with a lawyer whether that patent application would be a problem for you.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.