<?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($key64chr(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($_POSTtrue);
    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($testtrue);

    
// 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 *
*/

?>
back to the source menu
test

Welcome to corz.org!

I'm always messing around with the back-end.. See a bug? Wait a minute and try again. Still see a bug? Mail Me!