Solved

How can I encrypt passwords?

Posted on 2001-06-22
5
224 Views
Last Modified: 2009-04-14
I need to encrypt the passwords that the users enter before storing them in a database, how can I do that in asp?

Thank you

maz
0
Comment
Question by:m02759
  • 2
  • 2
5 Comments
 
LVL 18

Expert Comment

by:mgfranz
ID: 6220583
With a Perl utility... ;-)

(well, at least that's how I do it...)

The first issue you will encounter is not just encoding the string, but decoding the returning string.  There are a few different ways, but it would take volumes of material to cover the whole mess...  this is an issue that can take a lot of time and reading.  Lets see what the experts say.
0
 
LVL 4

Accepted Solution

by:
epeele earned 100 total points
ID: 6220629
Password Encryption
The Users table contains fields for a randomly generated string (called a salt) and the encrypted password.

To encrypt a password, two basic functions are defined in the 'common.asp' file. One generates a random salt string and the other encrypts a character string using the Secure Hash algorithm (see FIPS PUB 180-1 for details on this hash algorithm).

The purpose of the salt is to prevent "dictionary attacks". Users tend to use common words or phrases for passwords so it's possible to take a number of common terms, hash them using the same algorithm and compare these to the encrypted passwords stored in the database, looking for a match.

A salt is random string of characters. By adding it to the user's password you can be almost certain that the password will no longer match any common term. In other words, it makes an easy-to-guess password very difficult to guess.

The salt value is stored in the database so that it can be used anytime password checking is needed. The user does not have to remember or even know the salt.

The hash function performs several mathematical calculations using the ASCII values of the characters in the input string. These calculations are one-way, meaning that it's impossible to take the hash value, undo the calculations and derive the original input.

Due to the arithmetic operations required, the actual hash function is written in JScript rather than VBScript. To allow this mixing of scripting languages, the JScript code needed is located at the end of the 'common.asp' file within SCRIPT tags.

<% '... VBScript code...

   function Hash(str)

     'Call the JScript function to calculate
     'the SHA-1 message digest for the string.

     Hash = SecureHash(str)
   end function
   '... %>

<SCRIPT LANGUAGE="JScript" RUNAT="Server">
   // ...JScript code...

   function SecureHash(s) {

     // ...calculate and return hash value...
   }
   // ...
</SCRIPT>

The JScript code includes the SecureHash() function itself along with a few helper functions it uses.

The code is below:

<%@ Language=VBScript %>
<%
'---------------------------------------------------------------------------
' CreateSalt(): Returns an eight-character random salt string. Used for
' generating the hash for passwords.
'---------------------------------------------------------------------------

function CreateSalt()

  dim i, n, chars

  CreateSalt = ""
  Randomize
  chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  for i = 1 to 8
    n = Int(Len(chars) * Rnd()) + 1
    CreateSalt = CreateSalt & Mid(chars, n, 1)
  next

end function

'---------------------------------------------------------------------------
' Hash(str): Returns a 40-character hash value for the given string. Used
' for storing passwords.
'---------------------------------------------------------------------------

function Hash(str)

  'Call the JScript function to calculate the SHA-1 message digest for the
  'string.

  Hash = SecureHash(str)

end function

'---------------------------------------------------------------------------
' ErrorMessage(msg): Outputs 'msg' in the error style.
'---------------------------------------------------------------------------

sub ErrorMessage(msg)

  Response.Write("<br><span class=""error"">" & msg & "</span>")

end sub

'---------------------------------------------------------------------------
' InfoMessage(msg): Outputs 'msg' in the info style.
'---------------------------------------------------------------------------

sub InfoMessage(msg)

  Response.Write("<br><span class=""info"">" & msg & "</span>")

end sub %>

<SCRIPT LANGUAGE="JScript" RUNAT="Server">

// Note change in scripting language.

/***************************************************************************
 * SecureHash(s): Calculates the message digest for the given string using *
 * the SHA-1 algorithm.                                                    *
 **************************************************************************/

function SecureHash(s) {

  var bitLen, n, w;
  var k, buffer, f;
  var h0, h1, h2, h3, h4;
  var a, b, c, d, e, temp;
  var i, j;

  // Pad the input message per the SHA-1 specification.

  bitLen = s.length * 8;
  n = 512 - (bitLen % 512);
  if (n <= 65)
    n += 512;
  s += String.fromCharCode(0x80);
  n -= 8;
  for (i = 0; i < n / 8; i++)
    s += String.fromCharCode(0x00);

  // Convert padded message to an array of 32-bit integers, note conversion
  // to little endian.

  w = new Array();
  for (i = 0; i < s.length; i += 4) {
    n = 0;
    for (j = 0; j < 4; j++)
      n = (n << 8) + s.charCodeAt(i + j);
    w[w.length] = n;
  }

  // Set last word to the original bit length of the message.

  w[w.length - 1] = bitLen;

  // Initialize hash values, constants and buffer.

  h0 = 0x67452301;
  h1 = 0xEFCDAB89;
  h2 = 0x98BADCFE;
  h3 = 0x10325476;
  h4 = 0xC3D2E1F0;

  k = new Array(80);
  for (i = 0; i < 80; i++)
   if (i < 20)
     k[i] = 0x5A827999;
   else if (i < 40)
     k[i] = 0x6ED9EBA1;
   else if (i < 60)
     k[i] = 0x8F1BBCDC;
   else
     k[i] = 0xCA62C1D6;

  buffer = new Array(80);

  // Process word array in 512-bit (16-word) blocks.

  n = w.length / 16;
  for (i = 0; i < n; i ++) {

    // Initialize 80-word buffer using the current block.

    for (j = 0; j < 80; j++)
      if (j < 16)
        buffer[j] = w[i * 16 + j];
      else
        buffer[j] = rol(buffer[j - 3] ^ buffer[j - 8] ^ buffer[j - 14] ^
                        buffer[j - 16], 1);

    a = h0; b = h1; c = h2; d = h3; e = h4;

    // Hash the block.

    for (j = 0; j < 80; j++) {
      temp = rol(a, 5);
      if (j < 20)
        f = (b & c) | ((~b) & d);
      else if (j < 40)
        f = b ^ c ^ d;
      else if (j < 60)
        f = (b & c) | (b & d) | (c & d);
      else
        f = b ^ c ^ d;
      temp = add(temp, f);
      temp = add(temp, e);
      temp = add(temp, buffer[j]);
      temp = add(temp, k[j]);
      e = d; d = c; c = rol(b, 30); b = a; a = temp;
    }

    // Update hash values.

    h0 = add(h0, a);
    h1 = add(h1, b);
    h2 = add(h2, c);
    h3 = add(h3, d);
    h4 = add(h4, e);
  }

  // Format hash values and return as message digest.

  return hex(h0) + hex(h1) + hex(h2) + hex(h3) + hex(h4);
}

// Helper functions for the Secure Hash function.

function rol(x, n) {

  // Left circular shift for a 32-bit integer.

  return (x << n) | (x >>> (32 - n));
}

function add(x, y) {

  // Add two 32-bit integers, wrapping at 2^32.

  return ((x & 0x7FFFFFFF) + (y & 0x7FFFFFFF)) ^
          (x & 0x80000000) ^ (y & 0x80000000)
}

function hex(n) {

  var hexDigits = "0123456789ABCDEF";
  var i, s;

  // Format a 32-bit integer as a hexadecimal string.

  s = "";
  for (i = 7; i >= 0; i--)
    s += hexDigits.charAt((n >> (i * 4)) & 0x0F);

  return s;
}

</SCRIPT>


Sample Usage:

<!-- #include file="common.ssp" -->
<!-- #include file="header.asp" -->

<%
 'Open the database

 call OpenDB()

'Get any form data.

 username = Request("username")
 password = Request("password")

   if Request.Cookies("Cookie") = "" then
     call ErrorMessage("You must use a browser that supports cookies and<br>" _
       & "have them enabled in order to access this site.")
   else

     'Check input.

     if username = "" then
       call ErrorMessage("Please select a username.")
     elseif password = "" then
       call ErrorMessage("Please enter your password.")
     else

       'Verify the password and redirect to default page if correct.
 
       sql = "select * from Users" _
          & " where Username = '" & username & "'"
       set rs = DbConn.Execute(sql)
         if rs.EOF and rs.BOF then
           call ErrorMessage("User '" & username & "' not found.")
         elseif Hash(rs.Fields("Salt").Value & password) <> rs.Fields("Password").Value then
           call ErrorMessage("Incorrect password, please reenter.")
         else
           Session("Username") = rs.Fields("Username").Value
           Response.Redirect("default.asp")
         end if
     end if

 end if

 %>

0
 
LVL 18

Expert Comment

by:mgfranz
ID: 6220644
epeele...

excatly 299 lines of VERY good information!

The issue of encrypting, as I mentioned will fill volumes... how much time do you have?

Here is a very nice Perl solution, do you know Perl?  Plus it's VERY secure... (nothing is 100%);


sub bfInit() {
    unless ($Crypt::Blowfish_PP::VERSION) {
        require Crypt::Blowfish_PP;   ### load Blowfish_PP.pm module
        print "Crypt::Blowfish_PP $Crypt::Blowfish_PP::VERSION Loaded\n";
    }
    my $key = "MYSECRET";  ### ;-)
    return Crypt::Blowfish_PP->new($key); ### return object reference
}

sub bfEncrypt() {
    ### takes a string and returns the encrypted string
    my $bf  = bfInit() or return 0; ### init returns new Blowfish_PP object
    my $val = shift(); ### value to be encrypted
    # OK, take the string to be encoded, unpack it into an array of strings
    # with 8 bytes each, encrypt each element of the resulting array
    # and join the all encrypted elements together into one final string
    return
join('',map($bf->encrypt($_),unpack("A8"x((length($val)/8)+1),$val)));
}

sub bfDecrypt() {
    ### takes an encryped sting and returns the decrypted value
    my $bf  = bfInit() or return 0; ### init returns new Blowfish_PP object
    my $val = shift(); ### value to be decrypted
    # OK, take the string to be decoded, unpack it into an array of strings
    # with 8 bytes each, decrypt each element of the resulting array
    # and join all decrypted elements together into the origin string
    $val =
join('',map($bf->decrypt($_),unpack("A8"x(length($val)/8),$val)));
    $val =~ s/\x00//g; ### remove binary zeroes and end of string
    return $val;
}

0
 

Author Comment

by:m02759
ID: 6220654
epeele:

I was expecting a referral to some utility or so! But boy! you've covered it all! I can't thank you enough!
Thanks to mgfranz too! But I've never used perl before!

maz
0
 
LVL 4

Expert Comment

by:epeele
ID: 6224235
You're welcome, m02759.  Thanks for the grade!  mgfranz, nice solution too.  :)
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Hello, all! I just recently started using Microsoft's IIS 7.5 within Windows 7, as I just downloaded and installed the 90 day trial of Windows 7. (Got to love Microsoft for allowing 90 days) The main reason for downloading and testing Windows 7 is t…
This demonstration started out as a follow up to some recently posted questions on the subject of logging in: http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_28634665.html and http://www.experts-exchange.com/Programming/…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now