Here is a challence/responce login script, I left out some code that set cookies and sessions.
What this does:
Server creates random value and stores it in a session.
Server creates an image with that value.
Sever send login page to client.
Clients types in name, password and the randomvalue from the image.
Client creates a hass from password and randomvalue.
Client send name and hashed password back to server.
Server creates a passwordhash using the randomvalue and password from DB.
If hashes are the same the user is granted access.
Note that user names are unique.
<?php
/*
Login:
Client says to server "Hank wants access"
Server says to client "Here is a Challence (random value)"
Clients create a hash from the password suplied by Hank, and the Challence suplied by Server using JavaScript
(the password actually is double hashed like this: sha1(sha1($password) . $randVal);
Server does the same thing by using the password has for Hank stored in a database using PHP.
Server compares the two hashes, if the are the same Server says to Client "Access granted for Hank";
Client says " Oki :)"
Else server says "This is not Hank's password :("
*/
session_start();
function login()
{
global $dbi;
if($_SERVER['REQUEST_METHOD'] == "POST")
{
/*
This what a database records could look like, passwords are stored as a SHA-1 Hash
$name = "Hank";
$pass = "9c2028963dc9f7fbb4cb30140428a210c61dbb2c"; // hash of ``wachtwoord''
*/
$result = sql_query("SELECT uid, name, pwd FROM user WHERE name = '".addslashes($_POST['name']."'", $dbi);
list($uid, $name, $pass) = sql_fetch_row($result);
if(($_POST['name'] == $name) && ($_POST['pass'] == sha1($pass . $randVal)) && ($randVal == $_SESSION['randVal']))
{
// Create session vars and set cookie
}
else
{
//Kick user
echo "username / password / check incorrect";
}
}
else
{
//Seed the number generator only needed for PHP < 4.2.0
mt_srand((double)microtime()*1234567);
//Create a ranodom Number
$_SESSION['randVal'] = mt_rand(100000,999999);
echo
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"> \n"
."<html> \n"
."<head> \n"
."<title>Login</title> \n"
."<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"> \n"
."<style type=\"text/css\"> \n"
."<!-- \n"
."input.button { \n"
." font-family: Arial, Helvetica, sans-serif; \n"
." font-size: 10px; \n"
." background-image: url(input_button.png); \n"
." background-repeat: no-repeat; \n"
." height: 25px; \n"
." width: 25px; \n"
." border: 0px; \n"
."} \n"
."input.text{ \n"
." font-family: Arial, Helvetica, sans-serif; \n"
." font-size: 10px; \n"
." width: 75px; \n"
."} \n"
.".text{ \n"
." font-family: Arial, Helvetica, sans-serif; \n"
." font-size: 10px; \n"
."} \n"
."--> \n"
."</style> \n"
."<script src=\"sha.js\" type=\"text/javascript\"></script> \n"
."<script language=\"JavaScript\" type=\"text/javascript\"> \n"
."<!-- \n"
." function setText(x) \n"
." { \n"
." if(x != '') \n"
." { \n"
." var Text = document.forms['submitForm'].elements['botCheck'].value; \n"
." newText = Text + x; \n"
." document.forms['submitForm'].elements['botCheck'].value = newText; \n"
." } \n"
." else \n"
." { \n"
." document.forms['submitForm'].elements['botCheck'].value = \"\"; \n"
." } \n"
." } \n"
// Create a SHA-1 Hash of the suplied password and the suplied value (this is the number in the image and session)
." function encrypt() \n"
." { \n"
." var botCheck = document.forms['submitForm'].elements['botCheck'].value; \n"
." var name = document.forms['submitForm'].elements['name'].value; \n"
." var pwd = hex_sha1(document.forms['submitForm'].elements['pass'].value); \n"
." pwd = hex_sha1(pwd + botCheck); \n"
." if(name != '' && botCheck != '') \n"
." { \n"
." if(isNaN(botCheck)) \n"
." { \n"
." alert(\"Please type the numbers as displayed in the image.\"); \n"
." } \n"
." else \n"
." { \n"
." document.forms['submitForm'].elements['pass'].value = pwd; \n"
." document.forms['submitForm'].submit(); \n"
." } \n"
." } \n"
." else \n"
." { \n"
." alert(\"You must fill in all the fields.\"); \n"
." } \n"
." } \n"
."// --> \n"
."</script> \n"
."<noscript> \n"
."<H3>You must have a Javascript enabled browser in order to access this application.</h3> \n"
."</noscript> \n"
."</head> \n"
."<body> \n"
."<table width=\"100%\" heigt=\"100%\"><tr><td align=\"center\" valign=\"middle\">\n"
."<form name=\"submitForm\" action=\"".$_SERVER['PHP_SELF']."\" method=\"post\"> \n"
."<table width=\"75\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"> \n"
." <tr> \n"
." <td colspan=\"3\" align=\"center\" class=\"text\">Name:</td> \n"
." </tr> \n"
." <tr> \n"
." <td colspan=\"3\" align=\"center\"><input name=\"name\" type=\"text\" class=\"text\" value=\"\" size=\"10\"></td> \n"
." </tr> \n"
." <tr> \n"
." <td colspan=\"3\" align=\"center\" class=\"text\">Password:</td> \n"
." </tr> \n"
." <tr> \n"
." <td colspan=\"3\" align=\"center\"><input name=\"pass\" type=\"password\" class=\"text\" value=\"\" size=\"10\"></td> \n"
." </tr> \n"
." <tr> \n"
." <td colspan=\"3\" align=\"center\" class=\"text\">Security Code:</td> \n"
." </tr> \n"
." <tr> \n"
." <td colspan=\"3\"><img src=\"index.php?op=img\" alt=\"Security Code\" border=\"0\"></a></td> \n"
." </tr> \n"
." <tr> \n"
." <td colspan=\"3\" align=\"center\"><input name=\"botCheck\" type=\"text\" size=\"10\" class=\"text\"></td> \n"
." </tr>\n"
." <tr> \n"
." <td width=\"25\"><input type=\"reset\" value=\"C\" class=\"button\" onFocus=\"blur()\" title=\"Clear form\"></td> \n"
." <td width=\"25\"> </td> \n"
." <td width=\"25\"><input type=\"button\" value=\"ok\" class=\"button\" title=\"Login\" onClick=\"encrypt()\" onFocus=\"blur()\"></td> \n"
." </tr> \n"
."</table> \n"
."</form> \n"
."</td></tr>\n"
."</body> \n"
."</html> \n"
;
}
}
// Create the image to display randVal
function img()
{
header("Content-type: image/png");
$im = imagecreate(75, 15);
$backgroundColor = imagecolorallocate($im, 222, 222, 255);
$textColor = imagecolorallocate($im, 0, 0, 0);
$borderColor = imagecolorallocate($im,49,49,125);
imagestring($im, 4, 12, 0, $_SESSION['randVal'], $textColor);
//Draw 3 line trough the image, this makes ORC scanning harder
for($i=0; $i<2; $i++)
{
$color = imageColorAllocate($im, rand(0, 255), rand(0, 255), rand(0, 255));
imageline($im,5,rand(0, 15),70,rand(0,15),$color);
}
//Draw a nice border
imageline($im, 0, 15, 0, 0, $borderColor);
imageline($im, 0, 0, 75, 0, $borderColor);
imageline($im, 0, 14, 75, 14, $borderColor);
imageline($im, 74,14, 74, 0, $borderColor);
imagepng($im);
imagedestroy($im);
}
switch($_GET['op'])
{
case "img":
img();
break;
default:
login();
break;
}
?>