ASP Authentication Using XOR Encryption
by Valko Yotov
Introduction
This article explains how to control application access by validating the user's login and
password against a SQL 2000 database. Once validated, the user gets a one time pad Access Code
generated by SQL 2000 server, which is different and unique for every login - Access
Code changes on every user login - it is one time pad - OTP. Then the user's IP host address is
encrypted using Access Code and simple XOR and saved in database (XOR-based OTPs are
perfectly secure against cipher text-only cryptanalysis)..
On all restricted pages we include the access validation routine and if the user's IP does not match
against the saved one, the user does not get access. None of the asp pages use sessions or cookies
for communication.
Avoiding Session use drastically improves your web site performance, as does explicitly
declaring variables you use in your asp pages. Therefore including the following 2 lines of code:
<%@ Language=VBScript enablesessionstate=false %>
<% Option Explicit %>
at the top of every asp page you write is well worth the effort.
The Access Code is transmitted over your application's restricted access pages in hidden form
variable, and you just use a simple function to encrypt and compare current user's IP host
address Access Code with that one created and saved in the database during login.
We generate the Access Code using SQL 2000 server uniqueidentifier data type - it stores 16-byte
binary values that operate as globally unique identifiers (GUIDs). A GUID is a unique binary
number; no other computer in the world will generate a duplicate of that GUID value.
Here is T-SQL code for generating our Access Code table:
CREATE TABLE [ACCESS_CODE] (
[ACCESS_CODE_ID] uniqueidentifier ROWGUIDCOL NOT NULL ,
[USER_ID] [int] NOT NULL ,
[USER_HOST_IP] [nvarchar] (250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
CONSTRAINT [ACCESS_CODE_PK] PRIMARY KEY CLUSTERED
(
[ACCESS_CODE_ID]
) ON [PRIMARY]
) ON [PRIMARY]
GO
Note that uniqueidentifier columns may contain multiple occurrences of an individual
uniqueidentifier value, unless the UNIQUE or PRIMARY KEY constraints are also specified
for the column. Also note ROWGUIDCOL property indicates that the uniqueidentifier values
in the column uniquely identify rows in the table. The property does not do anything to
enforce this, however. The uniqueness is enforced as specifying the PRIMARY KEY constraint
for the column.
Other T-SQL code is self-describing. It creates database called MyLoginDB, table USER_ACCESS
for user data, table ACCESS_CODE for Access Code and user's host IP address, populates 2
rows with test user's data, and then create the 4 stored procedures needed. Note the second one
called sproc_CreateNewAccessId is used to create new Access Code. If an old Access Code already exists,
sproc_CreateNewAccessId deletes Access Code first, then creates new one - unique for
every user's login!
We have login.asp page, which validates user's email and password against the database. Function
FncGetPass returns a recordset form database and if user's email exist and passwords match we
give him access rights:
set rsPass = FncGetPass (strUserName,objConn)
if rsPass.bof and rsPass.eof then 'no data!
boolEmailExists = false
else
boolEmailExists = true
strTemp = rsPass("USER_PASS")
strUserId = rsPass("USER_ID")
If strTemp = strPassword Then
boolPassExists = true
Else
boolPassExists = false
End If
end if
Both variables boolEmailExists and boolPassExists are set to true and then we call function
FncCreateNewAccessId passing for argument already validated current user's id:
If boolEmailExists Then
If boolPassExists Then
strAccess = FncCreateNewAccessId (strUserId, objConn)
If for that user's id exist old Access Code FncCreateNewAccessId deletes Access Code first,
then creates new one - unique for every user's login! FncCreateNewAccessId also returns
strAccess variable, which is our GUID in format like this - {4A5325A6-1B14-471E-91A9-C93722A690E9}.
Then we encrypt user's host IP address using XOR algorithm:
strAccess = FncCreateNewAccessId (strUserId, objConn)
strHostIPEncrypted = EnDeCryptXOR(strAccess, strHostIP)
And using for encryption password new Access Code, we can be sure that at any given time moment
no more then one user can use same credentials simultaneously - Access Code is unique for every
user's login.
Then we call procedure called SendFormHTML(ByVal AccessCode) which gets for argument our newly
created Access Code, creates HTML form with Access Code in hidden form variable, and
automatically submit our new form to Main.asp page.
In Main.asp page we get again current calling host IP address using:
strHostIP = Request.ServerVariables("REMOTE_HOST")
and our Access Code in hidden form variable:
strAccessCode = request.form("txtAccessCode")
Then we call procedure CheckAccessRights with arguments Access Code and current page Host IP
address, it encrypts current page Host IP address using for password Access Code, and then it
checks in database and if does not exist same Access Code or saved in database host IP do not
match current Host IP, it redirects user back to login.asp page:
'=================================================================
'This function checks User's Access Rights
'-----------------------------------------------------------------
Sub CheckAccessRights(ByVal AccessCode, ByVal HostIP)
Dim objConn, rsAccessCode
Dim strHostIPEncrypted, strHostIPEncryptedFromDB
HostIP = Trim(CStr(HostIP))
HostIP = Replace(HostIP,".","")
strHostIPEncrypted = EnDeCryptXOR(AccessCode,HostIP)
Call Database_ConnOpen(objConn, strConnect)
set rsAccessCode = FncGetAccessCode (AccessCode,objConn)
if rsAccessCode.bof and rsAccessCode.eof then 'no data!
Response.Redirect "login.asp?msg=1"
else
strHostIPEncryptedFromDB = rsAccessCode("USER_HOST_IP")
If strHostIPEncryptedFromDB = strHostIPEncrypted Then
' do nothing user has valid access
Else ' back to login
Response.Redirect "login.asp?msg=1"
End If
end if
Call ADODB_CleanObject(rsAccessCode)
Call ADODB_CleanObject(objConn)
End Sub
'=================================================================
If check is successful we call modMainHTML procedure with argument Access Code and again the
same way we create HTML form with Access Code in hidden form variable, but this time we do not
submit it programmatically - lets users do some work instead ;-)
I think you get the idea now - just pass on from page to page our Access Code in hidden form
variable and check it with CheckAccessRights procedure to be sure that Dr. Evil do not try to
fool you. Beware from the Dark Side and may the force be with you!
Happy Programming!
Valko
Download
For brevity and simplicity the rest of the code is not listed here.
All the code, including the SQL scripts, can be found in the following zip file:
LoginAuthXOR.zip (6 KB).
Links
- ASP Authentication Using IP Address by Alain Trottier