| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
||||
|
||||
|
ASP Login Code Using Password Hash/Salt
I guess I was bored and wanted to experiment with Logins, Hashes, and Salts (Oh My!) So I wrote this:
When making a login script, its best practice to put the user's passwords through one way encryption to create a hash. A hash can not be converted back into the previous string so if anyone gets a hold of your user db, they can’t see the passwords. This hash is then stored in the database. At this point, you'd think you're safe. But, you'd be wrong. What if someone did gain access to your db? What if that same someone put 10,000,000 of the most common passwords through the same encryption and compared those hashes to the ones in your db? They would then compare the pre generated hashes to the ones in your db and if they found one, would then have access to your application. To prevent this, you add a salt to the hash, in this case the user name. This concatenates the username and password to create a hash that should be significantly more secure. I've also seen randomly generated salts that are also stored in the db, so you could go that way. In the end, all you're really doing is making sure that someone would have to compile a new set of hashes for each user, thus negating the effectiveness of the attack. Index.asp Code:
<% @Language=VBScript %>
<% Response.Buffer = True %>
<%
'Stops people at the door. Sends them to the login page.
If NOT Session("AllowAccess") = 1 Then Response.Redirect("includes/login.asp")
%>
<html>
<head>
<title>Tyler's Top Secret Page</title>
</head>
<body>
<h1>If you're seeing this, you logged in!</h1>
</body>
</html>
Login.asp Code:
<%@Language=VBScript%>
<html>
<head>
<title>Login Page</title>
<!-- Here's the include for the file with the hash functions -->
<!-- #include file = "hex_sha1_js.asp" -->
</head>
<body>
<%
Dim adoCon
Dim strSQL
Dim rs
Dim un
Dim pw
Dim pwhash
'Accessing a local variable is always faster than using the request method. So, if you're going to access a variable, it's best practice to set them locally.
un = Request("un")
pw = Request("pw")
'This just makes sure that the un and pw aren't empty, otherwise, the hash would throw an error.
If un <> "" AND pw <> "" Then
pwhash = hex_sha1(un & strPassWord)
Else
pwhash = ""
End If
'If the register new user link is clicked or the register form submitted, register will be equal to 1.
If Request("Register") = 1 Then
'If the register form was submitted, Confirm will be equal to 1.
If Request("Confirm") = 1 Then
'Here, the program creates a db connection and inserts the username and password/salt hash.
Set adoCon = Server.CreateObject("ADODB.Connection")
adoCon.Open "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("/login/login.mdb")
Set rs = Server.CreateObject("ADODB.Recordset")
strSQL = "INSERT INTO users(un,pw) values('" & un & "','" & pwhash & "')"
rs.open strSQL, adoCon
Response.Write("<h2>New User Registration Successful</h2><a href=""login.asp"">Back</a>")
adoCon.Close
Set adoCon = Nothing
Set rs = Nothing
Else %>
'This displays the new user registration form
<h2>New User Registration</h2>
<form action="login.asp?Register=1" method="POST" name="frmLogin">
<input type="hidden" name="Confirm" value="1" />
User Name: <input type="text" name="un" /> <br /><br />
Password: <input type="text" name="pw" /> <br /><br />
<input type="Submit" Value="Submit" />
</form>
<% End If
ElseIf un <> "" Then
'This checks the database and determines if there's a row matching the username and then if the password/salt hash matches what was submitted.
Set adoCon = Server.CreateObject("ADODB.Connection")
adoCon.Open "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("/login/login.mdb")
Set rs = Server.CreateObject("ADODB.Recordset")
strSQL = "SELECT un, pw FROM users WHERE un = '" & un & "'"
rs.open strSQL, adoCon
If rs.EOF Then
Response.Write("<h2>Login Unsuccessful. Either Username or Password incorrect.</h2><a href=""login.asp"">Back</a>")
ElseIf rs("pw") = pwhash Then
Session("AllowAccess") = 1
Response.Write("<h2>Login Successful!</h2><a href=""../index.asp"">Continue</a>")
adoCon.Close
End If
Set adoCon = Nothing
Set rs = Nothing
Else
'If all else fails, then they must be calling it to log in. So, here is the login form.
%>
<h2>Login</h2>
<form action="login.asp" method="POST" name="frmLogin">
User Name: <input type="text" name="un" /> <br /><br />
Password: <input type="text" name="pw" /> <br /><br />
<input type="Submit" Value="Submit" /> <br />
<a href="login.asp?Register=1">Register New User</a>
</form>
<% End If
%>
</body>
</html>
I took this from this post: http://forums.aspfree.com/code-bank...hash-82166.html hex_sha1_js.asp Code:
<script language="javascript" type="text/javascript" runat="server">
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
</script>
(EDIT: I put in some comments and explained my purpose a little more, so it looked like a code bank entry instead of a code eval)
__________________
If I've been helpful to you then: 1) Please click the scales icon ( ) in the upper right of my helpful post. This will make me popular, which god knows I need! 2) Send me copious amounts of cash. I prefer small bills stuffed into a burlap sack with a dollar sign. 3) Tell any single, good looking women that I exist, and that if they date me, they will have no further computer issues. That gets 'em every time. Last edited by trent2800 : October 31st, 2007 at 06:55 PM. |
|
#2
|
||||
|
||||
|
--moved to the Code Bank.
looking very good, thanks for sharing this with us! ![]() |
|
#3
|
|||
|
|||
|
v nice code
thanks |
|
#4
|
||||
|
||||
|
Quote:
we got reputation system here for this purpose. to increase your post count, you can spam the Lounge as much as you want. |
![]() |
| Viewing: ASP Free Forums > Programming > Code Bank > ASP Login Code Eval |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|
|
|