📜 ⬆️ ⬇️

Secure login with hashed password

When developing one project, a task appeared to implement protection in the case of viewing traffic, and viewing the source code (they can learn the password hash) by attackers. Having access to all data, no one should log in to the server without knowing the original password. Options for changing the IP address, getting a password directly at the time of entry (keylog), or eliminating bruteforce, this is no longer a concern of the web site.

The password will not be transmitted over the network, therefore hashing is used directly in the browser, for this I use the small JavaScript library SHA-1 . Why SHA-1, and not, say, MD5? It is believed that SHA-1 is a bit more reliable, and the JavaScript library itself is smaller than the same (on the same site) for MD5.

Instead of the password itself, the hash2 = sha1_hmac(login, password) is transmitted, but it is not the server that is stored on the server, but its hash with the login: sha1_hmac(hash2, login) . This cuts off the ability to log in if someone stole the hashed data from the server, for example, took it from a database, or read a php file, if the hash data is in it, as in the example below.

To protect against intercepted traffic, a hash generated on the basis of random data, IP address, and a reverse hash based on the login password is transmitted with an authorization form: hash1 = sha1_hmac(password, login); key = sha1(hash1, random_key+remote_addr) hash1 = sha1_hmac(password, login); key = sha1(hash1, random_key+remote_addr) . A randomly generated key for hashing is stored in the session.
')
Example:
In the file we store two hashes based on the login and password, one reverse sha1_hmac(pass, login) , and one straight double sha1_hmac(sha1_hmac(login, pass), login) .
The login does not change with me, since for my task it is so necessary, anyone can do as they please (it is enough to replace type="hidden" with type="text" ).
Source code auth.php :
<?php

$login = 'test';
//echo hash_hmac( 'sha1', 'pass', $login).'<br>';
$pass1 = '7cc031be8f6cf4073cc4302af78a0c7f555620cb';
//echo hash_hmac( 'sha1', hash_hmac('sha1', $login, 'pass'), $login).'<br>';
$pass2 = '186e9f6871599932a75ba9c4d2be6e858ebbc268';

function key_session($regenerate = false ) {
if (isset($_SESSION[ 'key']) and ! $regenerate) {
$key = $_SESSION[ 'key'];
} else {
$key = hash_hmac( 'sha1', microtime(), mt_rand());
$_SESSION[ 'key'] = $key;
}
return $key;
}

function auth() {
global $login, $pass1, $pass2;
$key = key_session();
$remote_addr = $_SERVER[ 'REMOTE_ADDR'];
$hash = hash_hmac( 'sha1', $key.$remote_addr, $pass1);
if (($_POST[ 'key'] === $hash) and (hash_hmac('sha1', $_POST['password'], $login) === $pass2)) {
//unset($_SESSION[ 'key']);
key_session( true );
$_SESSION[ 'remote_addr'] = $remote_addr;
header( 'Location: auth.php?mode=login');
} else {
$key = key_session( true );
echo <<<EOF
<script type= "text/javascript" src= "sha1.js" ></script>
<script type= "text/javascript" src= "jquery-1.4.2.min.js" ></script>
<form name= "auth" action= "auth.php" method= "post" >
<input type= "hidden" name= "remote_addr" value= "$remote_addr" >
<input type= "hidden" name= "key" value= "$key" >
<input type= "hidden" name= "login" value= "$login" >
$login:
<input type= "password" name= "password" value= "" >
<input type= "submit" >
</form>
<script>
var key = $( 'input[name=key]').val();
var remote_addr = $( 'input[name=remote_addr]').val();
$( 'form[name=auth]').submit(function() {
var login = $( 'input[name=login]').val();
var password = $( 'input[name=password]').val();
var key_hash = hex_hmac_sha1(hex_hmac_sha1(login, password), key+remote_addr);
$( 'input[name=key]').val(key_hash);
var pass_hash = hex_hmac_sha1(password, login);
$( 'input[name=password]').val(pass_hash);
});
$( 'input[name=password]').focus();
</script>
EOF;
}
}

session_start();
if (isset($_SESSION[ 'remote_addr']) and ($_SESSION['remote_addr'] === $_SERVER['REMOTE_ADDR'])) {
if ($_GET[ 'mode'] === 'logout') {
unset($_SESSION[ 'remote_addr']);
auth();
} else {
print_r($_SESSION);
echo '<a href="?mode=logout">Exit</a>';
}
} else {
auth();
}

* This source code was highlighted with Source Code Highlighter .


Download sources: auth.zip

Example: auth.php - password: pass

PS jQuery is used because I need it in the future, in principle, it is not necessary for the above.

PPS note that the order of arguments in the hashing function in JavaScript is inverse than in the same PHP functions

Source: https://habr.com/ru/post/85698/


All Articles