Password Help

  • Doctor Who 2 (6/29/2012)


    Just a followup question. Steve mentioned, in this article, KeePass and Password Safe. Until I read his article I'd never heard of either. So I've done a web search, and am getting results to different websites to download them. That makes me very uncomfortable.

    Bottom line: what's the links to both of these products, please?

    http://passwordsafe.sourceforge.net/

    I see someone already posted the peepass.info site.

    Dave

  • The two links posted above work. There are also versions in some mobile stores. I have a port for iOS and for OSX as well.

  • Steve Jones - SSC Editor (6/29/2012)


    The two links posted above work. There are also versions in some mobile stores. I have a port for iOS and for OSX as well.

    I'm very embarrassed. I'm sorry, I hadn't noticed that you did provide links to both in your post which started this thread.

    Rod

  • Yet another password security breach in which the company did not use a salt value when hashing the password:

    http://www.pcworld.com/article/258941/password_protection_101_lessons_from_the_eharmony_data_breach.html#tk.nl_dnx_t_crawl

    I wish I had the drive and resources to contact every company I could and teach them how to properly do this. Someone needs to get the word out.

    Steve, what does SqlServerCentral.com do to store passwords and authenticate users? If it's not a hash with a four or five byte salt, then I would gladly help out to fix the problem.

  • kevin77 (7/8/2012)


    Yet another password security breach in which the company did not use a salt value when hashing the password:

    http://www.pcworld.com/article/258941/password_protection_101_lessons_from_the_eharmony_data_breach.html#tk.nl_dnx_t_crawl

    I wish I had the drive and resources to contact every company I could and teach them how to properly do this. Someone needs to get the word out.

    Steve, what does SqlServerCentral.com do to store passwords and authenticate users? If it's not a hash with a four or five byte salt, then I would gladly help out to fix the problem.

    Is there a decent article on this or have you just volunteered to write this kevin77? 😉

    Gaz

    -- Stop your grinnin' and drop your linen...they're everywhere!!!

  • kevin77 (7/8/2012)


    Steve, what does SqlServerCentral.com do to store passwords and authenticate users? If it's not a hash with a four or five byte salt, then I would gladly help out to fix the problem.

    We use a hash, but I'll have to ask. I didn't write the routine. Our first iteration stored them encrypted, but retrievable. We removed that after a year or so and went to the hash. We do throw the login routine to SSL to limit man-in-the-middle attacks on that part of the site.

  • Is there a decent article on this or have you just volunteered to write this kevin77?

    Since this is a SQL site, I have to say I've never seen it done in SQL before so don't know if there are any articles. But on the client or server side, in just about any programming language, you should be able to find many examples.

    Our first iteration stored them encrypted, but retrievable. We removed that after a year or so and went to the hash.

    Yeah, those are the two use cases. If all you ever have to do is authenticate a user, then you should store a salted hash of the user's password. If, however, you have to impersonate the user, then you have no choice but to store the user's password using two way encryption. You then have to do all you can to protect your encryption key(s).

    Here is sample code application in C# and attached is a Zip file of a Visual Studio 2010 solution (of course, there is nothing special about the solution, it's just the one file):

    using System;

    using System.Security.Cryptography;

    namespace PasswordHashTest

    {

    /// <summary>Test class shows how to hash and store a password with a salt value.</summary>

    public class Program

    {

    /// <summary>The number of bytes used when creating a random value (salt) to be concatinated with a

    /// user's password when performing a hash. Salt values help prevent reverse dictionary lookups,

    /// also known as Rainbow Tables.</summary>

    private const int PasswordSaltLength = 4;

    /// <summary>We'll use this variable as our data store for this example.</summary>

    private static string PasswordHashStoredInDatabase = String.Empty;

    static void Main(string[] args)

    {

    CreateAndStorePasswordHash("SqlServerCentral.com rocks!");

    // Read the password entered by the user.

    Console.WriteLine("Please enter the password.");

    if (VerifyPassword(Console.ReadLine()))

    {

    Console.WriteLine("The password you entered is correct.");

    }

    else

    {

    Console.WriteLine("Incorrect password.");

    }

    // Press the Enter key to exit.

    Console.WriteLine("Press any key to exit.");

    Console.ReadLine();

    }

    private static void CreateAndStorePasswordHash(string plainTextPasswordFromApplication)

    {

    byte[] salt = CreateRandomSalt();

    // Store this string in a single column in the database.

    string hashedPassword = HashText(plainTextPasswordFromApplication, salt);

    PasswordHashStoredInDatabase = hashedPassword;

    }

    private static bool VerifyPassword(string plainTextPasswordFromApplication)

    {

    // Now you want to authenticate a user, so get the hashed password from the database based

    // upon the username they entered.

    string passwordHashFromDatabase = PasswordHashStoredInDatabase;

    byte[] databasePasswordBytes = Convert.FromBase64String(passwordHashFromDatabase);

    byte[] originalSalt = new byte[PasswordSaltLength];

    // We know the salt is stored in the first bytes.

    Array.Copy(databasePasswordBytes, 0, originalSalt, 0, originalSalt.Length);

    if (passwordHashFromDatabase == HashText(plainTextPasswordFromApplication, originalSalt))

    {

    return true;

    }

    return false;

    }

    /// <summary>Performs an SHA1 hash of the <paramref name="text"/> and <paramref name="salt"/> value

    /// and returns the result as a Base64 encoded string.</summary>

    /// <param name="text">Any text string to hash.</param>

    /// <param name="salt">A random array of bytes to be hashed along with <paramref name="text"/> that

    /// will prevent the use of reverse lookup dictionaries and 'Rainbow Tables'.</param>

    /// <returns>A Base64 encoded string that contains bytes of the resulting SHA1 hash of the

    /// <paramref name="text"/> and <paramref name="salt"/>. When decoded from Base64 to a byte array,

    /// the first <see cref="PasswordSaltLength"/> number of bytes represent the salt value that was

    /// used. This allows the hash to be stored in one field and also allows you to compare the hash

    /// of another text value, such as a password, to the original by sending in the new text value

    /// and the salt from the original hash.</returns>

    private static string HashText(string text, byte[] salt)

    {

    SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();

    // Convert the original string to an array of bytes.

    byte[] textBytes = System.Text.Encoding.UTF8.GetBytes(text);

    // Combine the salt bytes with the text bytes.

    byte[] bytesToHash = new byte[salt.Length + textBytes.Length];

    // The salt bytes go first, then the text bytes.

    Array.Copy(salt, 0, bytesToHash, 0, salt.Length);

    Array.Copy(textBytes, 0, bytesToHash, salt.Length, textBytes.Length);

    // Compute a hash of the text combined with the salt will make a unique value such that you

    // cannot perform a reverse lookup on the hash.

    byte[] hashedBytes = sha1.ComputeHash(bytesToHash);

    // Finally, so that we can perform comparisons on the hashed value at a later date, we will

    // store the salt value at the beginning of the hashed array. The salt length must be known

    // and remain constant.

    byte[] storedHashArray = new byte[salt.Length + hashedBytes.Length];

    Array.Copy(salt, 0, storedHashArray, 0, salt.Length);

    Array.Copy(hashedBytes, 0, storedHashArray, salt.Length, hashedBytes.Length);

    return Convert.ToBase64String(storedHashArray);

    }

    /// <summary>Returns a random salt value returned as a integer.</summary>

    /// <returns>A byte array of random bytes.</returns>

    private static byte[] CreateRandomSalt()

    {

    byte[] saltBytes = new byte[PasswordSaltLength];

    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

    rng.GetNonZeroBytes(saltBytes);

    return saltBytes;

    }

    }

    }

  • 96 bit salt used here (12 bytes)

  • Thanks kevin77.

    I was wondering if anyone had done more of the solution in SQL Server and thought that was the way to go? And if so, why?

    Gaz

    -- Stop your grinnin' and drop your linen...they're everywhere!!!

Viewing 9 posts - 31 through 38 (of 38 total)

You must be logged in to reply to this topic. Login to reply