Server Time:
Monday May 12 2008 07:05 AM  
Your Time:
  
HostMySite.Com is sponsoring this tutorial, please visit their site today!
This tutorial is sponsored by HostMySite.Com - ColdFusion Hosting

Password encryption for increased security using keys
by: Peter Tilbrook
Email this tutorial to a friend Display Printer Friendly Format
[Download in PDF Format] [Download in FlashPaper Format]

Password encryption for increased security using keys

You might have already noticed that even database servers like Microsoft's SQL Server 2000 have no method of hiding even password fields from prying eyes. Instead passwords are stored as plain text. Not good. Even Microsoft Access provides a way to mask fileds you would prefer not to be easily read. Not so SQL Server - and probably quite a few other database servers suffer the same issue.

This is easily rectified however using two handy functions built-in to ColdFusion, from at at least version 5.0 and above (I think they were in 4.x also). I've developed the following code using CFMX updated 3.

The Problem

Many database servers, including MS SQL Server 2000, will store even fields you designate as a "password" as freely readable text. MS Access allows you to mask a field with characters like your typical HTML form password field. But how secure is it?

You might have access to Secure Sockets Layer (SSL) to encrypt user logins between the client and server - but what happens if other people have access to your database and can read passwords because they are not encrypted or masked in any way? Who do you trust? Using SSL and this method together is an ideal solution. If you cannot use SSL you should at least implement this solution to protect your passwords.

The Solution

The solution is simple. The same technique can be used across multiple sites/applications. We are going to use an application specific "key" to use for encrypting and decryption our passwords. Without the key it is difficult - if not impossible - for the data to be read. The advantage of this solution is that you might use the same password across multiple sites. But with a unique "key" the same password in a database will be different to the same password in another database.

I don't suggest you use this method for "super user" or administration accounts - utilise your OS security for that wherever you can.

The Code

application.cfm

Starting with our "application.cfm" file we are going to define the encryption key.

Add the following lines to the application.cfm file of the application you wish to protect:

<cfif not isdefined("Request.PasswordKey")>
     <cfparam name=
"Request.PasswordKey" default="L2OIhfkjsyIJHK23jhfkuIYU">

</cfif>

We are using the REQUEST scope because it is available to ALL areas of the application and does not require locking (as in application/session variables). Because the application.cfm template is executed before every other template we test if it exists first (CFIF NOT ISDEFINED) - if it doesn't use CFPARAM to set the default. Future iterations of application.cfm will ignore the code in future (unless the server is restarted). The REQUEST scope is ideal for values that rarely change like DataSource Names, Administrator email addresses, Copyright messages, etc.

Important: make the default key value as random as you can.

Using the ColdFusion ENCRYPT function

Encrypt uses a symmetric key-based algorithm in which the same key is used to encrypt and decrypt a string. The security of the encrypted string depends on maintaining the secrecy of the key. Encrypt uses an XOR-based algorithm that uses a pseudo-random 32-bit key based on a seed passed by the user as a parameter to the function. The resultant data is UUencoded and may be as much as three times the original size (keep this in mind when setting the storage limit of your password field in your database).

Below is an example of a password (stored in MS SQL Server) AFTER it has been encrypted using a custom key (not the one above mind you):

%34*4E%P

In order to utilise encryption we need to let the user "register" so that we can encrypt their password. Your user will complete a HTML form and submit the form to our action page. Though not necessary it would be better to use SSL here.

User completes standard Register Now form and submits to our form action page:

<cfset Encrypted = Encrypt(Form.UserPassword, Request.PasswordKey)>
<cfset Form.UserPassword = #Encrypted#>

<cfinsert datasource=
"#Request.DataSourceName#"
             tablename="Users"
            
formfields="UserFirstName,UserLastName,UserPassword,UserEmailAddress">

Assuming no errors have occured your users account will now contain the password they submitted - but in an encrypted form according to the key we defined in the application.cfm.

User now needs to login to our application

In order for our user to gain access to our application we now need to "decrypt" their stored password. Easy with the login form action page like below:

<cfset Encrypted = encrypt(Form.UserPassword, Request.PasswordKey)>
<cfquery name=
"MailingListUpdate" datasource="#Request.DataSourceName#">
SELECT  ID,
            UserFirstName,
            UserLastName,
            UserPassword,
            UserEmailAddress
FROM     Users
WHERE   EmailAddress = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Form.UserEmailAddress#"> 
      AND UserPassword = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Encrypted#">
</cfquery>

User wants to "update" their details

To allow a user to do things like change their password we need to un-encrypt, or decrypt, their password and populate the form password field:

<cfoutput query="UserUpdate">
   <cfform name="UserUpdate" action="index.cfm">
    <table width="100%" border="0">
    <tr>
        <td halign=
"left" valign="top">
            <h5>Password:</h5>
        </td>
        <td halign="left" valign="top">
            <cfinput type="text" name="password"
                        maxlength=
"16" size="20"
                        required=
"yes"
            message=
"Please enter in a password"
            value=
"#Decrypt(Password,Request.PasswordKey)#">&nbsp;<sup>*</sup>
        </td>
    </tr>

        <input name="ID" type="hidden" value="#ID#">
        <input name=
"fuseaction" type="hidden" value="SaveChanges">
    <tr>
   
     <td>&nbsp;</td>
       <td valign=
"top" align="center"><input type="Submit" value=" Save Changes " style="cursor:hand"></td>
    </tr>
    </table>

</cfform>
</cfoutput>

When re-submitted to the database we re-use the encrypt code just as we did when the user registered to encrypt any changes.

Easy!


Date added: Mon. April 14, 2003
Posted by: Peter Tilbrook | Views: 19962 | Tested Platforms: CF4,CF5,CFMX | Difficulty: Intermediate
Categories Listed: Best Practices Databases

HostMySite.Com is sponsoring this tutorial, please visit their site today!
This tutorial is sponsored by HostMySite.Com - ColdFusion Hosting

This author's other tutorials:
Getting the TimeZone name
CFML's function GetTimeZoneInfo will give you timezone offsets, and day light savings time information, but if you want the name of the timezone your ColdFusion server is in you can use java's TimeZone class. - Date added: Thu. June 3, 2004
Getting Coldfusion Server Metrics
The often forgotten function GetMetricData() function returns the same info as the cfstat utility. - Date added: Thu. June 3, 2004
Why have my CFFORM's suddenly broken - using CFFORM in a hosted environment
If you are using the CFFORM tag in a shared hosting environment, and why wouldn't you as CF form elements can be very useful, you may now be receiving obscure JavaScript errors when your form loads. Never fear, the solution is a simple fix to an annoying problem - Date added: Tue. July 8, 2003
What version of CFMX is my host running?
As of writing this there are four flavours of CFMX, for Windows at least, floating about. You may know what version YOU are running but what about your hosting provider? Run the code below to find out. - Date added: Wed. May 7, 2003
Please rate this tutorial:
5 Stars 4 Stars 3 Stars 2 Stars 1 Stars
Comments on this tutorial
Read previous comments on this particular tutorial
What about Hiding the Password Key?
If a hacker has access to my database AND code, he has the encrypted password value, and by viewing the application.cfm he now has the password key. So he can just run the encrypt function himself to find the true value of the password.

How can I effectively hide the value of of the password key so that my CF pages know what it is, but it is not a field in a database column or a plaintext variable in the code???

Thanks in advance.
Posted by: Dominic Kelly
Posted on: 04/29/2004 05:48 PM
HASH
just hash it, store it in the db, and hash the form.password to compare before login.
use a question/answer validation to authorize to send email addy stored in db only with link to reset password.

hash hash hash.
Posted by: imstillatwork
Posted on: 05/12/2004 07:50 PM

in the page to reset password, generate new password, and email it to address in db. then the user can log in anc change password in standard users profile section.
Posted by:
Posted on: 05/12/2004 07:53 PM
Encryption
How to loop the database for plain text password field and encrypt the password, so that it can be used to login.
Posted by: RAM
Posted on: 06/03/2004 02:14 AM
re: Encryption
Just query the database for all the records with the password column you require. The output the query, assigning the encryption and updating the database as it goes. Eg:

<cfquery name="EncryptPasswords" datasource="#Request.DataSourceName#">
SELECT
ID, UserPassword
FROM Users
</cfquery>

<cfoutput query="EncryptPasswords">

<cfset Form.ID = #ID#>
<cfset Form.UserPassword = encrypt(Form.UserPassword, Request.PasswordKey)>

<cfupdate datasource="#Request.DataSourceName#" tablename="Users" formfields="ID, UserPassword">

</cfoutput>
Posted by: Peter Tilbrook
Posted on: 06/03/2004 02:34 AM
iam a message you
click here
Posted by: fahed
Posted on: 07/15/2004 12:27 PM
Use trim()
Always trim(form.variable) form variables. Certain browser, on Mac specialy add empty spaces upon submiting the form. A simple trim() around the submited var should take care of that. I always trim() my form vars.


Above example with trim():
<cfset Encrypted = encrypt(trim(Form.UserPassword), Request.PasswordKey)>

My 2
Posted by: Tomas
Posted on: 08/11/2004 09:50 PM
Better to Decrypt...
When comparing an encrypted database column to a form variable, I find it better to DECRYPT the encrypted value stored in the table, THEN compare to the form.variable instead of attempting to encrypt the form.variable and comparing to the queried value.


Posted by: DixieGal
Posted on: 03/11/2005 12:44 PM
cfc
I know this posting of the how to is old but.... I would find it more reliable to just make a cfc which you pass in your password in plain text (you have your key if you aren't going to make your own hash function) and then run the function and return the password as you will store it in a database. Could also be used to validate user entry.
Posted by: Christopher Jazinski
Posted on: 04/05/2008 01:25 PM
Post a new comment on this tutorial
post a new comment on this particular tutorial
Your Name:
Your Email:
Comment Title:
Comments:
Key Phrase:
 
Skyscrapper Banner Advertisement
ColdFusion Hosting by HostMySite

You are 1 of 615 active sessions! | Privacy | Company
Copyright © 2002 EasyCFM.Com, LLC. (Easy ColdFusion Tutorials) All Rights Reserved
All other trademarks and copyrights are the property of their respective holders.
ColdFusion Hosting ColdFusion Hosting
ADD TO:
Blink
Del.icio.us
Digg
Furl
Google
Simpy
Spurl
Y! MyWeb