corz.org uses cookies to remember that you've seen this notice explaining that corz.org uses cookies, okay!
<?php // ۞// text { encoding:utf-8 ; bom:no ; linebreaks:unix ; tabs:4sp ; }
if (isset($login['version'])){return;} else { $login['version'] = '0.3.1'; }
if (realpath ($_SERVER['SCRIPT_FILENAME']) == realpath (__FILE__)) {
die ( 'to err is human, human!' ); }
/*
simple php+javascript sha1 authentication..
[a proof-of-concept for my 'shaggie' pajamas plugin - to follow]
To use:
simply include this script at the top of your page..
include 'simple_php+javascript_sha1_login.php'; // rename it!
now the page is password**-protected.
If they submit a matching sha1 password hash (hmac), this script will silently
return control to your page. If not, it spits out its own login page.
The login page is just simple xhtml, you will probably want to edit that.
Note: you need to have Paul Johnson's sha1.js file (specified in the header,
below) available on your server, and in the correct location.
For a more fully-featured modular authentication system, check out pajamas..
https://corz.org/server/security/pajamas.php
have fun!
;o)
(or
© corz.org 2006->
** what the browser sends over the wires is an hmac digest of your password +
some random salt. if you don't have mhash (hmac) function, one is provided.
If you don't have sha1(), it uses 'sha.php' is a standalone version living
in the same folder as this script. a pajamas module will follow.
note: my_mhash() is available separately (as mhash()) as part of the pajamas
package, this is just a working demo of the php+javascript sha1 hashing.
*/
// prefs..
$login['pass'] = 'password';
// begin..
@ini_set('session.use_trans_sid', 'off');
@session_start();
// a logout event..
if (isset($_POST['logout'])) { unset ($_SESSION['pajamas']); }
// a hash was sent by the browser..
if (!empty($_POST['password'])) { $login['given_hash'] = $_POST['password']; }
else { $login['given_hash'] = ''; }
// already created a hash for this login? if not, do so..
if (empty($_SESSION['pajamas']['hash'])) { create_sha1_hash($login['pass']); }
// verify the given hash matches our stored hash..
if (!empty($_SESSION['pajamas']['hash']) and ($login['given_hash'] == $_SESSION['pajamas']['hash'])) {
$_SESSION['pajamas']['admin'] = true;
}
// authentication has failed..
if (empty($_SESSION['pajamas']['admin']) or $_SESSION['pajamas']['admin'] !== true) {
echo '<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
<meta http-equiv="content-type" content="application/xml; charset=utf-8" />
<title>simple php and javascript sha1 hashing login.. please enter your password</title>
<script type="text/javascript" src="sha1.js"></script>
</head>
<body onload="document.passform.password.focus()">
<div style="text-align:center; margin:50px 100px 20px 100px;">
<h2>simple php and javascript sha1 hashing login..</h2>
<h1>ACCESS DENIED!</h1>
<code>enter password..</code><br />
<br />
<form name="passform" method="post" action="',$_SERVER['SCRIPT_NAME'],'" ';
/*
note that the javascript function receives its variables in reverse order..
*/
echo '
onsubmit="password.value = hex_hmac_sha1(\''.$_SESSION['pajamas']['salt'].'\', password.value)">
<div class="form">
<input type="password" size="42" name="password" value="" autocomplete="off" />
</div>
</form>
</div>';
// This is simply to compare the results on a server where mhash is IS available.
run_tests($GLOBALS['login']['pass'], $_SESSION['pajamas']['salt']);
echo '
</body>
</html>';
die;
}
// you got this far, you must be authenticated..
return true;
/*
fin
*/
/*
homebrew mhash
computes the hash of a key (salt) and some data.
for servers without the mhash libraries available.
gleaned from various sections of the php manual, and the specs..
mhash: http://mhash.sourceforge.net/
FC2104: http://www.ietf.org/rfc/rfc2104.txt
mina86 at projektcode dot org
a part of pajamas..
https://corz.org/server/security/pajamas.php
For the most part, this operates as a drop-in replacement for mhash(), so
if you don't have the mhash libraries available, you can, at least with
the md5 and sha1 hashing algorithms, use this in exactly the same way.
Feel free to lift for your own projects.
have fun!
;o)
(or
© corz.org 2006->
usage:
string{binary} my_mhash ( string{algorithm}, string{data}, string{key} [, string{format}] )
eg. my_mhash('sha1', 'MyPassword', 'mySalt==', 'hex');
{algorithm}
can be one of either 'sha1' or 'md5' (you can also supply the php constants,
MHASH_SHA1, and MHASH_MD5, respectively, so it becomes a drop-in replacement
for the php function, sorta). If you send some other string, it may or may
not work, depending on your server's capabilities.
Any php can do 'md5', you need >=4.3 to do 'sha1', or else use functions/sha1.php
{format}
optionally, you can specify a return format, either 'hex' for hexidecimal output,
or 'b64' for base64 encoded output. hex is probably the most useful.
*/
function my_mhash() {
switch(func_get_arg(0)) {
case 'MHASH_SHA1': $algo = 'sha1'; break;
case 'MHASH_MD5': $algo = 'md5'; break;
default: $algo = func_get_arg(0);
}
$data = func_get_arg(1);
if (func_num_args() > 2) { $key = func_get_arg(2); } else { $key = ''; }
if (func_num_args() > 3) { $format = func_get_arg(3); } else { $format = ''; }
// simple key-less format, or else key was empty ('').
if (empty($key)) { return pack('H*', $algo($data)); } // mhash(MHASH_$algo, $data) [simple digest]
if (strlen($key) > 64) {
$key = pack('H*', $algo($key));
}
$key = str_pad($key, 64, chr(0x00));
$ipad = str_repeat(chr(0x36), 64);
$opad = str_repeat(chr(0x5c), 64);
$hash = $algo(($key ^ $opad).pack('H*', $algo(($key ^ $ipad).$data))); // (RFC 2104) HMAC
switch($format) {
case 'hex': // [hexidecimal]
return $hash;
break;
case 'b64': // [base64 encoded]
return base64_encode(pack('H*', $hash)); // base64 encoded version.
break;
default: // mhash [binary]
return pack('H*', $hash); // essentially, mhash(MHASH_$algo, $data, $key);
}
}
// create and store the correct hash..
function create_sha1_hash($data) {
// we're just gonna store this key server-side here, for simplicity, though we could easily create
$_SESSION['pajamas']['salt'] = make_key(); // a new key for each login attempt, store only the hash.
$_SESSION['pajamas']['hash'] = make_sha1_hash($data, $_SESSION['pajamas']['salt']);
}
// generate a random key for this hash..
function make_key() {
//return 'salt'; // for tests.
mt_srand((double)microtime()*1000000);
return base64_encode(pack("CCCC", mt_rand(), mt_rand(), mt_rand(), mt_rand())); // data
}
/*
return a hex version of the sha1 hash..
if available, we use php's built-in functions.
if not, we use our homebrew functions..
Now we just use homebrew functions.
Will need to update this to use pack('H*', hash('md5', $s)) or something.
*/
function make_sha1_hash($data, $key) {
if (!function_exists("sha1")) { // the built-in function is *much* faster,
include 'sha1.php'; // but if you don't have it, this works great.
}
return my_mhash('sha1', $data, $key, 'hex');
}
// if (function_exists("hash")) {
// return bin2hex(mhash('MHASH_SHA1', $data, $key));
// } else { // bin2hex(my_mhash('MHASH_SHA1', $data, $key)); is identical.
// return my_mhash('sha1', $data, $key, 'hex');
// }
// compute a few things..
//
function run_tests($data, $key) {
echo '<pre>';
echo 'POST array: ', print_r($_POST, true);
echo 'session array: ', print_r($_SESSION['pajamas'], true);
$test['data'] = $data; // here so they show in our output $test
$test['key'] = $key; // array, yet are clearer to read, below..
// compute a few hashes..
if (function_exists('mhash')) { $test['1-php_hex_mhash-simple'] = bin2hex(mhash('MHASH_SHA1', $data)); }
$test['2-my_mhash_hex-simple'] = bin2hex(my_mhash('sha1', $data));
// if (function_exists('mhash')) { $test['3-php_base64_mhash'] = base64_encode(mhash('MHASH_SHA1', $data, $key)); }
// if (function_exists('mhash')) { $test['4-php_hex_mhash'] = bin2hex(mhash('MHASH_SHA1', $data, $key)); }
$test['5-my_base64_mhash'] = base64_encode(my_mhash('MHASH_SHA1', $data, $key));
$test['6-my_hex_mhash'] = bin2hex(my_mhash('MHASH_SHA1', $data, $key));
$test['7-my_mhash_base64'] = my_mhash('sha1', $data, $key, 'b64');
$test['8-my_mhash_hex'] = my_mhash('sha1', $data, $key, 'hex');
// if (function_exists('mhash')) { $test['9-php_hex_mhash_md5'] = bin2hex(mhash('MHASH_MD5', $data, $key)); }
$test['10-php_hex_mhash_md5'] = bin2hex(my_mhash('MHASH_MD5', $data, $key)); // should be same as above
$test['11-my_mhash_md5_hex'] = my_mhash('md5', $data, $key, 'hex'); // ditto
echo "\n\nsome homebrew hmac tests: ",print_r($test, true);
// what hashes are available on the server?
/*
$mc = mhash_count();
echo "\n\navailable mhash libraries.. \n\n";
for ($i = 0 ; $i <= $mc ; $i++) {
if (mhash_get_hash_name($i)) {
echo ' ',mhash_get_hash_name($i),' [blocksize: ',mhash_get_block_size($i),"]\n";
}
}
*/
echo '</pre>';
}/*
if..
[data] => password
[key] => salt
test returns..
[1-php_hex_mhash-simple] => 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
[2-my_mhash_hex-simple] => 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
[3-php_base64_mhash] => wdDgaZgwWQOsdvWJu9bUthpnC6Y=
[4-php_hex_mhash] => c1d0e06998305903ac76f589bbd6d4b61a670ba6
[5-my_base64_mhash] => wdDgaZgwWQOsdvWJu9bUthpnC6Y=
[6-my_hex_mhash] => c1d0e06998305903ac76f589bbd6d4b61a670ba6
[7-my_mhash_base64] => wdDgaZgwWQOsdvWJu9bUthpnC6Y=
[8-my_mhash_hex] => c1d0e06998305903ac76f589bbd6d4b61a670ba6
[9-php_hex_mhash_md5] => 961ff2373921d4eadfe97e4ccc56d3e2
[10-php_hex_mhash_md5] => 961ff2373921d4eadfe97e4ccc56d3e2
[11-my_mhash_md5_hex] => 961ff2373921d4eadfe97e4ccc56d3e2
in pajamas, this is coupled with Paul Johnson's client-side JavaScript hashing functions.
(using strict RFC padding "=") to send hashes from the browser.
hex_hmac_sha1('salt', 'password') [hex] => c1d0e06998305903ac76f589bbd6d4b61a670ba6 * shaggie use this one *
b64_hmac_sha1('salt', 'password') [b64] => wdDgaZgwWQOsdvWJu9bUthpnC6Y= * also handy *
*/
?>