This sounds a bit hairy, especially if the clocks on the sending and receiving sides are out of sync, so with that in mind, I keep the
password chosen for 100 seconds, this gives a reasonable chance of authentication if the clocks are 'nearly' in sync, and only uses the minute of the hour to determine which password to use. This obviates the need to have the timezone of each machine the same as well as the date and hours do not matter. The passwords are all 128 characters long, but could be any length, and even variable length, so long as the delimiter chosen for the password database file is guaranteed not to appear in a password. Passwords are never sent over the network, rather a hash of the password is sent, and compared with a corresponding hash at the remote end. Currently I am using the md5 hashing algorithm. Generating the Passwords I created the following to generate the initial password database. Put this code into a file, maybe call it genpw.php, and call it from the command line. It will output the passwords to stdout so you will probably want to redirect that to a file. The passwords are all 128 characters long and contain random choices of character from ascii 33 (a !) to ascii 126 (a ~). <?php function genPassword($length=128) { $op=""; for($x=0;$x<$length;$x++){ $op.=chr(rand(33,126)); } return $op; } for($x=0;$x<100;$x++){ echo genPassword() . "n"; } ?>
Copy the resulting file to a location outside the webroot of your site, but in a place that php can get to. On my server I have created an include directory above the public_html directory where I store stuff that I want php to be able to get at, but not the web server itself to serve those files. I also protect that directory with a restrictive .htaccess file, just in case. Using the Passwords
I use the following code to obtain the current password: <?php // obtain the passwords into an array $pw=file("/location/of/the/password/file"); // get the unix epoch, and divide by 100 to give a 'window' of 100 seconds $num=intval(date("U")/100); // cast the variable to a string $num.=""; // grab the last two digits off the end of the string $num=substr($num,-2); // cast the result back to an integer $num=intval($num+0); // obtain the md5 hash of the password indexed by the current minute from the array of passwords $hash=md5($pw[$num]); ?>
If you now design your site update forms to have a password hash field, and run the same code at your workstation, against the same database of passwords, the hashes should be in sync with each other.
It then becomes a trivial matter to compare the hashes and bail out or not depending on the result. Other Uses
It occurs to me that this would be quite useful as the basis of a one-time pad encryption system as well. So long as a secure way could be found to transfer the passwords file between the receiving parties, then it would take a great deal of effort to hack it, especially if the time basis was kept.
|