how to properly secure non-ssl logins (php + ajax)

Rene Veerman rene7705 at gmail.com
Sun Feb 15 07:30:33 EST 2009


Hi.

Recently, on both the jQuery(.com) and PHP mailinglists, a question has 
arisen on how to properly secure a login form for a non-ssl web-application.
But the replies have been "get ssl".. :(

I disagree, and think that with a proper layout of authentication 
architecture, one can really secure a login system without having the 
administrative overhead of installing SSL everywhere, and the monetary 
cost for a SSL certificate for each domain.

I wish to code such a solution into a really-free library (so probably 
LGPL or GPL + MIT) over the next 2 to 5 months.
This library would be a complete SQL, PHP & javascript package (jQuery 
"plugged in"), targetted for the novice programmer.

I'm halfway (or more?) there, i think.
For my own CMS, i have taken the following approach, which i'd like to 
hear your improvements on:

(For onewayHash() i have MD5 and SHA256 implementations in both JS and 
PHP..)

//// SQL:

create table users (
  user_id                   integer,
  user_login_name      varchar(250),
  user_login_hash      varchar(250),
  user_password_hash   varchar(250),
....other fields....
primary key (user_id)
);

create table preferences (
  pref_system_hash   varchar(250)
....
);

//// PHP (pseudo-code) , on system installation:
    preferences.pref_system_hash = onewayHash ( randomStringLength(100) );

//// PHP , on user-create:

   users[user_id].user_login_hash = onewayHash(user_login_name + 
preferences.pref_system_hash);
   users[user_id].user_password_hash = onewayHash 
("someGooodPasswordNot" + preferences.pref_system_hash);

//// PHP, on request of a login form:

   challenge = makeNewChallenge ();
        //checks since when [browser IP] has last received a new 
challenge, if < threshold : make a new challenge. else return old challenge.
       //a challenge is a random string (+ special chars) pushed through 
the onewayHash function.

   html = '
       <form id="loginForm">
          <input type="hidden" id="sh" name="sh" 
value="preferences.pref_system_hash">
          <input type="hidden" id="ch" name="ch" value="challenge">
          <input id="plain_user" name="plain_user"/>
          <input id="plain_pass" name="plain_pass"/>
          <input type="hidden" id="user_hash" name="user_hash"/>
          <input type="hidden" id="pass_hash" name="pass_hash"/>
       </form>
    ';
    sendHTMLtoBrowser (html);

//// Javascript: on page with login form:

    jQuery('#loginForm').submit (function () {
          var sh = jQuery('#sh')[0]; //same for ch, plain_user, 
plain_pass, all the inputs in the html form.
          ....

          user_hash = onewayHash ( onewayHash ( plain_user.value + 
sh.value ) + challenge );
          //same for pass_hash basically

          plain_user.value = ''; //clear out the plain text fields so 
they dont get transmitted (same for plain_pass ofcourse)

          jQuery.ajax ( /* submit login form through POST, handle 
results */ )
    }


//// PHP, on receiving the login form data:

       // walk through all the records in users table, for each, calculate:
          user_hash = onewayHash ( users[user_id].user_login_hash + 
challenge );
          pass_hash = onewayHash ( users[user_id].user_password_hash + 
challenge );

       // if they match what was sent, then it's the user we're looking 
for with the right password, so their $_SESSION['authenticated_user'] = 
updated.

////


If you have a completely alternative way of securing a non-ssl login 
form, i'd like to hear about it too.


---------------------------------------------------------------------
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majordomo at metzdowd.com



More information about the cryptography mailing list