Password encryption for increased security using keys

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!

All ColdFusion Tutorials By Author: Peter Tilbrook
  • 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.
    Author: Peter Tilbrook
    Views: 37,163
    Posted Date: Monday, April 14, 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.
    Author: Peter Tilbrook
    Views: 15,340
    Posted Date: Wednesday, May 7, 2003
  • 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
    Author: Peter Tilbrook
    Views: 22,337
    Posted Date: Tuesday, July 8, 2003
  • Getting Coldfusion Server Metrics
    The often forgotten function GetMetricData() function returns the same info as the cfstat utility.
    Author: Peter Tilbrook
    Views: 12,182
    Posted Date: Thursday, June 3, 2004
  • 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.
    Author: Peter Tilbrook
    Views: 12,696
    Posted Date: Thursday, June 3, 2004
Download the EasyCFM.COM Browser Toolbar!