tags:

views:

112

answers:

5
+5  A: 

Couple solutions stand out:

  • Store the names & classes in a database, and reference them with a numeric ID instead of passing the data in the request
  • Keep the information in the request, but add a secure hash that will prevent tampering with the data

The hash mechanism would be something like this:

When generating the link for the certificate, you have $name and $class. You'll create a third GET variable that is a hash of $name, $class, and a secret string that only your program knows. Something like this:

$salt = "this is my secret";
$hash = md5($name . $class . $salt);
$url = "http://www.mysite.com/certificate.php?name=" . urlencode($name) . "&class=" . urlencode($class) . "&hash=" . $hash;

Now when a user hits your certificate generation page, you must verify the hash:

$salt = "this is my secret";
$expected = md5($_GET['name'] . $_GET['class'] . $salt);
if ($expected != $_GET['hash']) {
  die("You are not authorized");
} else {
  // User is OK; generate the certificate
}
pix0r
I'm not at all familiar with secure hashes. Could you point me in the right direction for hashing part of a URL?
paracaudex
Hashing is sort of a one-way encryption. It's an easy way to turn "name-myname" into "A5BC2D1E", and it can't be reversed by the student. You can use this as a key to a lookup table.
Karl
Since I can't reverse it, is there any reason to use hashes over random numbers?
paracaudex
@paracaudex Yes, you don't have to store anything anywhere. The hash is the result of the public data (name/class) and your private data (salt). You can generate as many URLs as you want, without storing any data.
Tim Lytle
@pix0r +1 Was answering while you were, didn't see you answer until I had already posted - not trying to copy you.
Tim Lytle
A: 

Yes, if you want to limit your inputs to a fixed pool, then creating a database full of random keys is the way I would go.

If you want a quicker and dirtier way to do it, just generate the keys into a text file, use a script to pull the file apart to send them to the recipients, and have your PHP certificate generator read from a copy of the file on the server.

Tim Keating
Hmmm. Sounds like random keys is the way to go then. I'll give the text file route a shot first.
paracaudex
A: 

Should I just create a set of random numbers and associate these with the student/workshop pairs in a database?

Yes.

Col. Shrapnel
+1  A: 

Your best bet would be to have a list of students/classes (some kind of database) and only allow generation of allowed certificates. That way you don't need to obfuscate the name of the student or class, because only valid certificates can be generated.

If that's too much to ask - you could generate a MD5 hash based on the combination and some salt, then add that hash to the URL. That way the salt would need to be know to forge a URL.

http://www.example.com/makepdf.php?name=Tim&class=PHP&hash=c2c455ce438112b44499561131321126

Then the generation script just does this:

$hash = md5($_GET['name'] . $_GET['class'] . $salt);
if($hash != $_GET['hash']){
  //invalid request
}

Of course you'll need to generate the URL's with the same salt.

Tim Lytle
The trouble is the students know each other, and I wouldn't really want them generating each others' certificates. I guess I don't really want anything too transparent to the user. But maybe I'm wrong about this.
paracaudex
Using the hash method, the URL could only generate a single certificate, and the URLs for other certificates could not (easily) be determined.
Tim Lytle
Right. Is there an advantage to uses hashes over random numbers? Maybe I'm misunderstanding the concept here. In your example, does this mean that I should have code which, given a URL, recalculates the hash to make sure it matches? Or would I use a table, since the hash is obscure to me as well? Sorry, I don't know anything about encryption.
paracaudex
The code sample I get is recalculating the hash to make sure the URL has not been changed. I didn't show any way to generate the original URL (hint, it's the same process as regenerating it). The hash isn't obscure to you, because you know the salt. In fact, if you change the salt value, you essentially invalidate all the past URLs (could be useful).
Tim Lytle
Thanks! That makes sense.
paracaudex
A: 

Assuming you are generating these URLs yourself on the server, you could join all your parameter values together into a string:

hash_string = "myname:classname";

Then append a final parameter that's a hash of that string along with some secret seed:

query_string .= "&h=" . md5("my_secret_key:" . hash_string)

Then, when you get the query back, just check to make sure that the hash matches:

hash_string = params['name'] . ':' . params['class'];
if (params['h'] == md5("my_secret_key:" . hash_string)) ...

I don't really know PHP syntax, but you get the idea.