I wrote this a while ago, and have been adding to it a little bit at a time. This is the current version that I'm using. It allows me to do a number of things with encrypted urls.
In order to make this work, you need mcrypt installed.
This version also uses session_id() as the $key between the pages, which makes things interesting. Not only will the URL be encrypted, but it will only DECRYPT properly during that session. In other words, you as a user can not go to a page, copy the link, and email it to me, or save it for use later. But anyway, my point is, you must have session_start() before this file if you wish to make the session_key() the $key. Or you can use your own $key if you wish. I would also suggest that the beginning of the source and destination files look EXACTLY the same up till the point when this file is included. Otherwise, funky things sometimes happen, and the URL doesn't decrypt properly. In fact, I'd start every page like this:
<?php
session_start();
// Require encryption file
require("/functions/encryption.inc.php");
Before anyone jumps in to say that using the session_id() isn't very secure.... you're right. I just did it to see if I could. A way to get the advantage of a one time URL that can't be decrypted outside of the session is to create an actual $key phrase, and encrypt that with the session_id(), and use the resulting string as the actual URL encryption $key. Or, if you don't care about any of that, just put
$key = "this is my key";
at the top and be done with it.
The simple thing to do here, once you get this working is set up your link like this:
eventpage.php?<?php echo(encrypt($key, "semid=10&referrer=20")); ?>
By including this file on the source page AND the target page, and assuming you keep the $key the same between the pages, this file will automatically decrypt the encrypted URL and set the variables for you. So you don't have to do anything on the target page.
The other function included here came about when I would have something like this:
eventpage.php?<?php echo(encrypt($key, "semid=10&referrer=20&startdate=2005-01-01&enddate=2005-01-31&day=saturday&time=0700&color=blue&size=large")); ?>
...and I wanted to change JUST ONE THING in the string, regardless of what everything else in the string was. Let's say for example, I had a drop down box that let me change the day from saturday to something else. Without doing a bunch of "if(isset(whatever))"s, I needed a way to do that. Hence the updateURL() function.
This:
eventpage.php?<?php echo(updateURL(array("day" => "sunday"))); ?>
Will take all variables from the original encrypted URL, and change day to equal "sunday" instead of "saturday" and re-encrypt a new URL.
This:
eventpage.php?<?php echo(updateURL(array("day" => "null", "startdate" => "2005-01-15"))); ?>
Will take all variables from the original encrypted URL, change "startdate" from "2005-01-01" to "2005-01-15", and will remove the "day" variable from the variable list, and re-encrypt a new URL.
I hope this makes sense. There's still quite a bit of rem'd out debug stuff in this, but it's something that we use here and make changes to on a somewhat regular basis. It works fine right now as is on three of our servers, and it gets used by a lot of people using a variety of applications all day long every day. I created it just exactly for the reasons you stated. I might have a user who is allowed to see one site, but not another site, and I didn't want them snooping around by changing the URL. And now they can't. They can't even add "site=12" manually because if the variable string passed is not a hexadecimal string ("=" is not a hex character) then it deletes the variable string completely and continues like nothing happened.
Anyway, let me know if you get it to work for you.
Mark
<?php
/* encryption.inc.php
* 2004-01-20
* By Mark Marshall
*
*/
// The key will be different for each session.
if(!isset($key)) {
$key = session_id();
}
function encrypt($key, $text) {
// Generate an initialization vector
$iv = substr(md5($key), 0, mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_ECB));
// Generate the encrypted text
$encrypted = bin2hex(mcrypt_encrypt (MCRYPT_CAST_256, $key, $text, "ecb", $iv));
return $encrypted;
}
function decrypt($key, $encrypted) {
/* incoming: should be the $key that you encrypted with
* $encrypted is the encrypted string (encrypted text)
* returns plain text
*/
// generate an initialization vector
$iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_ECB));
// Convert the hex back to a binary string
$binary_encrypted = hex2bin($encrypted);
// now we do our normal decrypting
$text = mcrypt_decrypt (MCRYPT_CAST_256, $key, $binary_encrypted, "ecb", $iv);
// Return the answer
return trim(chop($text));
}
function hex2bin($data) {
$len = strlen($data);
return pack("H" . $len, $data);
}
function setvariables($decr) {
$variables=array();
$vars=explode("&", $decr);
for($i=0; $i < count($vars); ++$i) {
$element=explode("=", $vars[$i]);
if(IsSet($element[1])) {
$variables[$element[0]] = $element[1];
}
}
return $variables;
}
function updateURL($changes) {
global $decrypted;
global $key;
$newLinkDecrypted = $decrypted;
if(!$newLinkDecrypted) $newLinkDecrypted = "encryptedLink=yes";
reset($changes);
while(list($varKey, $varVal) = each($changes)) {
// echo "$key => $val\n";
if(!strcasecmp($varVal, "null")) {
// Erase the variable from the link if it's there
// echo("NEED TO ERASE THIS ONE!<br />");
$position = strpos(strtolower($newLinkDecrypted), strtolower(($varKey ."=")));
if($position === false) {
// echo("NOT FOUND AT ALL <br />");
// It's not in the string at all, so just keep $decryped as is and drop out...
//$newLinkDecrypted = $decrypted;
} else {
// echo("FOUND AT LOCATION: ". $position ."<br />");
// If it's the first variable in the link...
if($position == 0) {
// echo("FOUND AT THE BEGINNING OF THE STRING...<br />");
$endPosition = strpos($newLinkDecrypted, "&", $position) + 1;
$newLinkDecrypted = substr($newLinkDecrypted, $endPosition);
} else {
// Let's check the rest of the string...
$position = strpos(strtolower($newLinkDecrypted), strtolower(("&". $varKey ."=")));
if($position <> 0) {
// echo("FOUND LATER IN THE STRING...<br />");
$endPosition = strpos($newLinkDecrypted, "&", $position + 2) +1;
$newLinkDecrypted = substr($newLinkDecrypted, 0, $position) ."&". substr($newLinkDecrypted, $endPosition);
}
}
}
} else {
// Look for it in the string somewhere other than the first spot (has an "&" in front of it)...
// echo("<strong>RegExp Test: (^|&)". $varKey ."=[a-z.A-Z0-9-]*&</strong> ");
if(eregi(("(^|&)". $varKey ."=[a-z.A-Z=, _0-9-]*&"), $newLinkDecrypted)) {
// echo("FOUND IT!<br />");
// Found it --- Now where is it?
$position = strpos(strtolower($newLinkDecrypted), strtolower(($varKey ."=")));
// echo("FOUND AT LOCATION: ". $position ."<br />");
// If it's the first variable in the link...
if($position == 0) {
// echo("FOUND AT THE BEGINNING OF THE STRING...<br />");
$endPosition = strpos($newLinkDecrypted, "&", $position) + 1;
// echo("End Position: ". $endPosition ."<br />");
$newLinkDecrypted = $varKey ."=". $varVal ."&" .substr($newLinkDecrypted, $endPosition);
} else {
// Let's check the rest of the string...
$position = strpos(strtolower($newLinkDecrypted), strtolower(("&". $varKey ."=")));
if($position <> 0) {
// echo("FOUND LATER IN THE STRING...<br />");
$endPosition = strpos($newLinkDecrypted, "&", $position + 2) +1;
$newLinkDecrypted = substr($newLinkDecrypted, 0, $position)
."&". $varKey ."=". $varVal ."&". substr($newLinkDecrypted, $endPosition);
} else {
// Else it's not in the string at all, so just keep $decryped as is and drop out...
//$newLinkDecrypted = $decrypted;
}
}
} else {
// echo("NOT FOUND! --- ADDING!<br />");
$newLinkDecrypted=$varKey ."=". $varVal ."&". $newLinkDecrypted;
//$newLinkDecrypted .= $decrypted;
}
}
}
$newLink = encrypt($key, $newLinkDecrypted);
return $newLink;
}
// print_r($_SERVER['argv']);
// unset($_SERVER['argv'][0]);
// If an argument has been passed, check it first...
If(isset($_SERVER['argv'][0])) {
// If argv[0] is NOT a hex only string, unset argv[0] and continue like nothing happened.
if(!preg_match("/^([0-9a-fA-F])*$/", $_SERVER['argv'][0])) {
unset($_SERVER['argv'][0]);
}
}
// If argv[0] is still set, decrypt it
If(isset($_SERVER['argv'][0])) {
$encrypted=$_SERVER['argv'][0];
$decrypted=decrypt($key, $encrypted); // <-- NEED TO BUILD SOME CHECKS INTO THIS
// $variables=setvariables($decrypted); <-- DON'T NEED THE VARIABLES FUNCTION ANYMORE
$variables=array();
$variables['encryptedLink'] = 'yes'; // <-- DON'T NEED $VARIABLES[] ANYMORE
$string=explode("&", $decrypted);
$numVars = count($string);
for($i=0; $i < $numVars; ++$i) {
${substr($string[$i], 0, strpos($string[$i], '='))} = substr($string[$i], strpos($string[$i], '=') + 1);
}
unset($numvars, $string);
}
?>