Solved

.net 4.0 password history example sql server

Posted on 2014-11-08
27
224 Views
Last Modified: 2015-01-17
Hi, I am looking for a good example of password history for user management.  Any good samples?  I think I woulg need to create the table, lookup, and salt/hash comparison.
0
Comment
Question by:atljarman
  • 13
  • 12
27 Comments
 
LVL 61

Expert Comment

by:btan
ID: 40431887
There is an old past that you may want to check out, it is .NET but not of latest v4 though
http://www.codeproject.com/Articles/15750/Simple-Password-Manager-Using-System-Security
..another I am thinking if can leverage on open source password mgr such as KeePass which is widely used
http://www.codeproject.com/Articles/5489/KeePass-Password-Safe
0
 

Author Comment

by:atljarman
ID: 40433053
Thank you.  I was looking for something more along these lines... http://ronanmoriarty.wordpress.com/2012/03/14/implementing-password-history-using-a-custom-membership-provider/

I'm not sure how to implement this for a forms project or how to use the entity provider.  This appears to be just what I need and I was able to get to the triggers.  After that, I'm stuck.
0
 

Author Comment

by:atljarman
ID: 40433239
This might be another approach.  My password history is stored in the database table phistory.  I'm trying to figure out how to add this logic to the backend of my password change page, but if it goes somewhere else that would be good to know.

http://forums.asp.net/t/1184599.aspx?How+to+enforce+password+uniqueness+verify+against+list+of+previous+passwords+

public class ProviderWithPasswordHistory : SqlMembershipProvider
{
protected static PasswordHistoryTableAdapters.T_PasswordHistoryTableAdapter taPasswordHistory;
protected static MembershipUser mu;

public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
taPasswordHistory = new PasswordHistoryTableAdapters.T_PasswordHistoryTableAdapter();
base.Initialize(name, config);
}
public bool PasswordAlreadyUsed(string pass)
{
mu = Membership.GetUser();
string strPasswordSalt = taPasswordHistory.GetMemberPasswordSalt(Membership.ApplicationName, mu.UserName);
byte[] bIn = Encoding.Unicode.GetBytes(pass);
byte[] bSalt = Convert.FromBase64String(strPasswordSalt);
byte[] bRet = null;
byte[] bAll = new byte[bSalt.Length + bIn.Length];
System.Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
System.Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
bRet = base.EncryptPassword(bAll);
string thepasswd = Convert.ToBase64String(bRet);

//Compare old passwords
DataTable dtPasswordHistory = taPasswordHistory.GetPasswordHistoryForAUser(Membership.ApplicationName, mu.UserName);
ArrayList arPasswordHistory = new ArrayList();
foreach (DataRow dr in dtPasswordHistory.Rows)
{
arPasswordHistory.Add(dr[0].ToString());
}
if (arPasswordHistory.Contains(thepasswd))
{
return true;
}
else
{
return false;
}
}

}
0
 
LVL 78

Expert Comment

by:David Johnson, CD, MVP
ID: 40433537
the logic would be
enter new password
check if password is in the history
call password history checker routine
if answer is yes display error message and go back to enter new password
if answer is no execute change password
return

password history
variables needed username and suggested password
get username
for each item in password history {
check if suggested password is equal to password history item if yes return = yes
}
remove oldest password from password history
insert suggested password
return no
0
 
LVL 61

Expert Comment

by:btan
ID: 40434027
you will definitely need a hashed password db where each password entered will be validated against the db and history records (e.g. restrict reuse count and passwd complexity etc). Actually there is a MembershipProvider.ValidatingPassword that can be leveraged upon to do the history check.

Along the line of the SQL membership, there should be some flow to get the intercept for the history check, I looked at forum and it seems to be the below.

In changepasswd.apsx (runat="server")
@ Page_load <script> Add in the method such as ChangepasswdFNC
@ ChangePasswdFORM declared <form> Add in at the button (or targeted trigger) to runat=server the ChangepasswdFNC

Next is to setup the Membership.ValidatingPassword e.g.
Declare a Method for PasswdChgInterceptSetup which has
Membership.ValidatingPassword += Membership_ValidatingPasswordFNC
(This occurs when a user is created, a password is changed, or a password is reset.)

Then inside  Membership_ValidatingPasswordFNC,
Declare the action for the Validation against your DB

I saw this EE posting which may be along the line for the validation and there are some suggested code. You can catch it too.
0
 

Assisted Solution

by:atljarman
atljarman earned 0 total points
ID: 40434708
Thanks for the help so far.  I've pulled together what I've found on this topic for something that seems to be close to working.  Most examples create a history table in the database with triggers then look up X number of previous passwords.  Most of these are done by deleting any password that is X + 1 or higher as stated above.

So I successfully interupted the change password method so that it would allow me to look up the old passwords.  The problem that I am facing is that I can't figure out how to compare the text in the input 'newpassword' to the password history.  I loop through each old password and attempt to figure out how to get the equivalent of hashed/encrypted password but I'm not having any luck.  I believe that I am pretty close to a solution... if I can get the history passowrd and my test password to match, I can set the variable to say that the match is true then prevent the function from completing with the message to the user saying to early to use the password.

Here is my code if you can see any issues with it:

    protected void ChangePassword1_ChangingPassword(object sender, LoginCancelEventArgs e)
{

        // Get a reference to the currently logged on user
        MembershipUser currentUser = Membership.GetUser();
        // Determine the currently logged on user's UserId value
        Guid currentUserId = (Guid)currentUser.ProviderUserKey;
        // Assign the currently logged on user's UserId to the @UserId parameter
        String UserId = currentUserId.ToString();


        string strConnection2 = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
 		string queryString = "SELECT * FROM PasswordHistory where UserId='" + UserId + "';";


        using (SqlConnection connection =
                   new SqlConnection(strConnection2))
        {
            SqlCommand command = new SqlCommand(queryString, connection);
            connection.Open();

            SqlDataReader reader = command.ExecuteReader();



            // Call Read before accessing data. 
            while (reader.Read())
            {

            	string pws = reader["PasswordSalt"].ToString();
            	string pw = reader["Password"].ToString();


				string hashOldPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(pw,"SHA1");

                //lblmessage.Text = lblmessage.Text + ", " +  EncodePassword("<test password>",  pws) + ": " + EncodePassword(pw,  pws) ;
                ///lblmessage.Text = lblmessage.Text +  "<br />" + pw + " " + pws ;
                lblmessage.Text = lblmessage.Text +  "<br />" + hashOldPassword  + " " + EncodePassword("<test password>", pws) + " " + FormsAuthentication.HashPasswordForStoringInConfigFile("<test password><test key>","SHA1");
            }

            // Call Close when done reading.
            reader.Close();
        }


    // do your lookup here, 
    bool passwordHasBeenPreviouslyUsed = true;

    if (passwordHasBeenPreviouslyUsed)
    {
        e.Cancel = true;
        // notify of error
                lblmessage.Text = "<p class='error'>" + lblmessage.Text + "   It is too early to reuse that password per security policy.</p>";
        return;
    }

}

    private static string CreatePasswordHash(string Password, string Salt)
{
    string passwordFormat = "SHA1";
    byte[] bytes = Encoding.Unicode.GetBytes(Password);
    byte[] src = Convert.FromBase64String(Salt);
    byte[] dst = new byte[src.Length + bytes.Length];
    byte[] inArray = null;
    System.Buffer.BlockCopy(src, 0, dst, 0, src.Length);
    System.Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);

    HashAlgorithm algorithm = HashAlgorithm.Create(passwordFormat);
    inArray = algorithm.ComputeHash(dst);

    return Convert.ToBase64String(inArray);
}

/*
Not sure where this encryption key is coming from, the web config machine key maybe???? 
*/

    private string Encrypt(string clearText)
{
    string EncryptionKey = "MAKV2SPBNI99212";
    byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
    using (Aes encryptor = Aes.Create())
    {
        Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        encryptor.Key = pdb.GetBytes(32);
        encryptor.IV = pdb.GetBytes(16);
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearBytes, 0, clearBytes.Length);
                cs.Close();
            }
            clearText = Convert.ToBase64String(ms.ToArray());
        }
    }
    return clearText;
}


    private string GetSHA1HashData(string data)
{
    //create new instance of md5
    SHA1 sha1 = SHA1.Create();

    //convert the input text to array of bytes
    byte[] hashData = sha1.ComputeHash(Encoding.Default.GetBytes(data));

    //create new instance of StringBuilder to save hashed data
    StringBuilder returnValue = new StringBuilder();

    //loop for each byte and add it to StringBuilder
    for (int i = 0; i < hashData.Length; i++)
    {
        returnValue.Append(hashData[i].ToString());
    }

    // return hexadecimal string
    return returnValue.ToString();
}

    public string EncodePassword(string pass, string salt)
{
	byte[] bytes = Encoding.Unicode.GetBytes(pass);
	byte[] src = Convert.FromBase64String(salt);
	byte[] dst = new byte[src.Length + bytes.Length + 1];
	System.Buffer.BlockCopy(src, 0, dst, 0, src.Length);
	System.Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
	System.Security.Cryptography.HashAlgorithm HashAlg = System.Security.Cryptography.HashAlgorithm.Create("SHA1");
	dynamic inArray = HashAlg.ComputeHash(dst);
	return Convert.ToBase64String(inArray);
}

Open in new window


Any thoughts on where I might be going wrong?
0
 
LVL 61

Accepted Solution

by:
btan earned 500 total points
ID: 40434743
From the "CreatePasswordHash", there isnt any call to though. Actually I was thinking the moduel for password comparison should be verified to see if it working before going into the intercepting part to isolate and ease troubleshooting. I do suggest review the hash password fnc standalone as in http://www.obviex.com/samples/hash.aspx
( a salt is generated, and it is recommended a unique salt per password (and also to per user). hence the use for salt RNG fnc. also salts can be public and store along password hash)

A simple salted hash check can be below too. I do note that there is no use of Encoding.Unicode type of function which in your case, you used that - probably we should avoid having that as Base64 is likely what we only need.
http://geekswithblogs.net/Nettuce/archive/2012/06/14/salt-and-hash-a-password-in.net.aspx

There is a library that may be useful for calling for testing
https://www.zetetic.net/blog/2012/7/3/secure-password-hashing-for-aspnet-in-one-line.html
0
 

Author Comment

by:atljarman
ID: 40436900
btan,

I am testing the zetetic library you suggested... Sorry I had to go backwards thinking it better to have a more secure password first.  

I'm not sure how to modify the salt so it is unique with each password (as it doesn't appear to change the password just the format of the hashed -possibly encoded - password).  Any ideas how to implement the unique salt.   Also, once I have the new hashed password type and salt, I'm not sure how to make the history work.  Any thoughts.

Thanks for the great suggestions.
0
 
LVL 61

Expert Comment

by:btan
ID: 40437130
I believe the sample link (http://www.obviex.com/samples/hash.aspx) already has stated to use below as example which is much better than hardcoding or grabbing from dictionary - best effort
// Generate a random number for the size of the salt.
            Random  random = new Random();
            int saltSize = random.Next(minSaltSize, maxSaltSize);

            // Allocate a byte array, which will hold the salt.
            saltBytes = new byte[saltSize];

            // Initialize a random number generator.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            // Fill the salt with cryptographically strong byte values.
            rng.GetNonZeroBytes(saltBytes); 

Open in new window

The salt is part of computing the hashed password so once that is done, it can be string (e.g. Base64 encoded) compared to the DB for any similar hit. I did not drill into the  Zetetic.Security package but since it is using PKCS#5 such as pbkdf2 it is also leveraging in this same strategy with supplied salt and password.
0
 

Author Comment

by:atljarman
ID: 40437221
btan,

I think I'm going to hold off on the salt for the moment and get back to the password history and comparison.  Now that I'm implementing the new package for the hashing should the function on this page http://geekswithblogs.net/Nettuce/archive/2012/06/14/salt-and-hash-a-password-in.net.aspx still allow you to hash the password without modification for comparison to the history of hashes?  I apologize for asking for verification.  I just had a ton a problems trying to match the new password proposed with the previous passwords.
0
 
LVL 61

Expert Comment

by:btan
ID: 40437539
yes it should as the salt is generated still from RNGCryptoServiceProvider
and is based on Rfc2898DeriveBytes which will take the password and salt and iteration counts to eventually create a unique key. thereafter, you can use this key for encryption, or even just encode that in base 62 for storage and comparisons which is done in the posting that I shared and mentioned in your prev post.
0
 

Author Comment

by:atljarman
ID: 40444758
Please do not close this question.  I was able to implement the enhanced hashing function but not the hash comparion capability using the form field comparing it to what is in the password history database.  I hope to do that this next week.
0
 

Author Comment

by:atljarman
ID: 40465067
Sorry for taking so long on this.  I've been a bit lost.  So It seems that the  Zetetic.Security functionality just replaces the core SHAxx hashing functionality and nothing else.  So in theory, if I could just then use http://geekswithblogs.net/Nettuce/archive/2012/06/14/salt-and-hash-a-password-in.net.aspx to hash the new password suggested by the user and compare it to the database values.  Is that correct?  From the link on this posting that you so kindly pointed out, really is not hashing any new hash type it is using the provider from within the membership provider of ASP .net.  The only thing that is being added (which someone could modify) is the creation of the salt that is also shown on that link.  Please let me know if that makes sense.  I'm going to try and implement this now that I've had some time to allow the thoughts to refresh.
0
Complete VMware vSphere® ESX(i) & Hyper-V Backup

Capture your entire system, including the host, with patented disk imaging integrated with VMware VADP / Microsoft VSS and RCT. RTOs is as low as 15 seconds with Acronis Active Restore™. You can enjoy unlimited P2V/V2V migrations from any source (even from a different hypervisor)

 
LVL 61

Expert Comment

by:btan
ID: 40465904
yes they are based on PBDKF2. The geekswith blog implements 1000 rounds iteration of the hash and for Zetetic it implement 5000 round. this deter the work factor of breaking through the hash, it may increased security level but also the performance may be impacted. you can try out then. There are sharing on this in Troy Hunt blog (http://www.troyhunt.com/2012/07/stronger-password-hashing-in-net-with.html) too

From Zetetic, see their sample and article
@ https://www.zetetic.net/blog/2012/3/29/strong-password-hashing-for-aspnet.html
The .NET Framework has included an implementation of Password Based Key Derivation Function 2 (PBKDF2) in the Rfc2898DeriveBytes class, going all the way back to .NET Framework 2.  However, Rfc2898DeriveBytes does not implement the HashAlgorithm method that would make it compatible with the ASP.NET SqlMembershipProvider or with other general-purpose programmatic .NET hashing interfaces.
0
 

Author Comment

by:atljarman
ID: 40466003
There is no luck here.  So I tried encoding, hashing, but i just can not get the new password to match what exists in the database.  It would be great to see a working example even if I had to go back to SHA1 or SHA256 (standard for .Net 4.0).
0
 

Author Comment

by:atljarman
ID: 40466032
Ok... this does not work.  I was looping through the database for one user with the same salt for with the passwords Test12, Test123, and Test1234.  I can not see what I am doing wrong here.  

    protected void ChangePassword1_ChangingPassword(object sender, LoginCancelEventArgs e)
{
        // Get a reference to the currently logged on user
        MembershipUser currentUser = Membership.GetUser();
        // Determine the currently logged on user's UserId value
        Guid currentUserId = (Guid)currentUser.ProviderUserKey;
        // Assign the currently logged on user's UserId to the @UserId parameter
        String UserId = currentUserId.ToString();

        string strConnection2 = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
 		string queryString = "SELECT * FROM PasswordHistory where UserId='" + UserId + "';";

        byte[] saltInDb = Convert.FromBase64String("Test1234");
        byte[] passWordBuffer = Encoding.Unicode.GetBytes("F7GnpjwvQHJtgkA0ZQVBEA==");
        byte[] completeHash = new byte[saltInDb.Length + passWordBuffer.Length];

        saltInDb.CopyTo(completeHash, 0);
        passWordBuffer.CopyTo(completeHash, saltInDb.Length);

        //byte[] hash2 = HashAlgorithm.Create(Membership.HashAlgorithmType).ComputeHash(completeHash); //pbkdf2_local
        byte[] hash2 = HashAlgorithm.Create("pbkdf2_local").ComputeHash(completeHash); //pbkdf2_local

        /*
        if (passwordRow.Password == Convert.ToBase64String(hash2))
        {
            return true;
        }
        */
        
        

        using (SqlConnection connection =
                   new SqlConnection(strConnection2))
        {
            SqlCommand command = new SqlCommand(queryString, connection);
            connection.Open();

            SqlDataReader reader = command.ExecuteReader();



            // Call Read before accessing data. 
            while (reader.Read())
            {

            	string pws = reader["PasswordSalt"].ToString();
            	string pw = reader["Password"].ToString();


				//string hashOldPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(pw,"SHA1");

                lblmessage.Text = lblmessage.Text + 
                    "<br />PW Stored:" + pw + 
                    "<br />Hash: " + ComputeHash("F7GnpjwvQHJtgkA0ZQVBEA==", "Test134") + 
                    "<br />Encode: " + EncodePassword("F7GnpjwvQHJtgkA0ZQVBEA==", "Test1234") + 
                    "<br />Test: " + Convert.ToBase64String(hash2);
            }

            // Call Close when done reading.
            reader.Close();
        }



    // do your lookup here, 
    bool passwordHasBeenPreviouslyUsed = true;

    if (passwordHasBeenPreviouslyUsed)
    {
        e.Cancel = true;
        // notify of error
                lblmessage.Text = "<p class='error'>" + lblmessage.Text + "   It is too early to reuse that password per security policy.</p>";
        return;
    }

}

    public string EncodePassword(string pass, string salt)
{
	byte[] bytes = Encoding.Unicode.GetBytes(pass);
	byte[] src = Convert.FromBase64String(salt);
	byte[] dst = new byte[src.Length + bytes.Length + 1];
	System.Buffer.BlockCopy(src, 0, dst, 0, src.Length);
	System.Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
    //System.Security.Cryptography.HashAlgorithm HashAlg = System.Security.Cryptography.HashAlgorithm.Create("SHA1");
    System.Security.Cryptography.HashAlgorithm HashAlg = System.Security.Cryptography.HashAlgorithm.Create("pbkdf2_local");
    //HashAlgorithm algorithm = HashAlgorithm.Create("pbkdf2_local");
	dynamic inArray = HashAlg.ComputeHash(dst);
	return Convert.ToBase64String(inArray);
}


    static string ComputeHash(string salt, string password)
    {
        var saltBytes = Convert.FromBase64String(salt);
        using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, saltBytes, 1000))
            return Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256));
    }

Open in new window



Here is the label that is populated on the page:
PW Stored:s6nkHBq9z9k44F6fWi3KBHW67JelsMGH
Hash: S51/CX3yozeba+hAQyz6WubgZtlIO6k7P7jFGe+ZNiWLv+3+6Y3HArvxLX1wFfiIDO4TBZg71qWCxw7rjHc5Z7ZWENkU4jIEyI/7mCIZN+zdQJubjlSwjvTHJ2Ymxy9wkhg2+W6VK+zSzp3YpDZ/LM74hByFkdb7Ln4XLaqiJCEnMc6wGuLW7flcWRZElL0pYub7FY+1SfXk8NRI71h0qwakq4QGgrkPZguBK5sbylUHaeQWK2Dz6hbwKOjub2HAowTbB4vt9pVuxFN1ow4GgW1pM9Tx+TAzZPQJ9ihsiPqh1f8mzWyhEI75HX/ZpssJLElqWXY/rdkaIRosYxRt9Q==
Encode: caKWaWxY28CjOUSH2xmwyJJio+Cg/J7Y
Test: caKWaWxY28CjOUSH2xmwyJJio+Cg/J7Y
PW Stored:RmAR3vDLBYMaPZ9ubnsM5MaFv6IikOBg
Hash: S51/CX3yozeba+hAQyz6WubgZtlIO6k7P7jFGe+ZNiWLv+3+6Y3HArvxLX1wFfiIDO4TBZg71qWCxw7rjHc5Z7ZWENkU4jIEyI/7mCIZN+zdQJubjlSwjvTHJ2Ymxy9wkhg2+W6VK+zSzp3YpDZ/LM74hByFkdb7Ln4XLaqiJCEnMc6wGuLW7flcWRZElL0pYub7FY+1SfXk8NRI71h0qwakq4QGgrkPZguBK5sbylUHaeQWK2Dz6hbwKOjub2HAowTbB4vt9pVuxFN1ow4GgW1pM9Tx+TAzZPQJ9ihsiPqh1f8mzWyhEI75HX/ZpssJLElqWXY/rdkaIRosYxRt9Q==
Encode: caKWaWxY28CjOUSH2xmwyJJio+Cg/J7Y
Test: caKWaWxY28CjOUSH2xmwyJJio+Cg/J7Y
PW Stored:fTDUB4FymYuoEkSxe2A71FC6zDROtCQb
Hash: S51/CX3yozeba+hAQyz6WubgZtlIO6k7P7jFGe+ZNiWLv+3+6Y3HArvxLX1wFfiIDO4TBZg71qWCxw7rjHc5Z7ZWENkU4jIEyI/7mCIZN+zdQJubjlSwjvTHJ2Ymxy9wkhg2+W6VK+zSzp3YpDZ/LM74hByFkdb7Ln4XLaqiJCEnMc6wGuLW7flcWRZElL0pYub7FY+1SfXk8NRI71h0qwakq4QGgrkPZguBK5sbylUHaeQWK2Dz6hbwKOjub2HAowTbB4vt9pVuxFN1ow4GgW1pM9Tx+TAzZPQJ9ihsiPqh1f8mzWyhEI75HX/ZpssJLElqWXY/rdkaIRosYxRt9Q==
Encode: caKWaWxY28CjOUSH2xmwyJJio+Cg/J7Y
Test: caKWaWxY28CjOUSH2xmwyJJio+Cg/J7Y

Open in new window


This is using the zetetic security one line security approach: https://www.zetetic.net/blog/2012/7/3/secure-password-hashing-for-aspnet-in-one-line.html  I can't even tell if this is formatting the password that is stored in the database correctly.
0
 
LVL 61

Expert Comment

by:btan
ID: 40466097
if you are trying to compare with existing password history table, the algorithm (like in your past - "bRet = base.EncryptPassword(bAll);") must be the same and not just the salt per se. even then the salt used in existing password history must be reused and with same algorithm (and padding) to create that match - for encoding it is to ensure the input and output for single entry processing are consistent format and length.
0
 

Author Comment

by:atljarman
ID: 40466098
Ok.  I'm using the membership provider to create the hash and salt.  How do you repeat that outside of the provider?   All examples I've tried have failed.
0
 
LVL 61

Expert Comment

by:btan
ID: 40466125
looks like VS 2010 and VS2012 have different, pls see under "Better hashing for young and old" and "Hashes ain’t hashes" section
...old SqlMembershipProvider to the new DefaultMembershipProvider...., Updating a 2010 project template is easy – and potentially catastrophic. The problem is simply that if you have an existing project with existing hashes, following the advice above will fundamentally break your authentication. Even if you migrate all the accounts from the old tables to the new (which is easy enough), the stored hashes from the old days will not match the new hashes from the PBKDF2 model. Nobody will be able to logon.
http://www.troyhunt.com/2012/07/stronger-password-hashing-in-net-with.html

Also it stated
Hashing algorithms always create the same cipher length regardless of the input string; it must mean that something different is going on. And there is – what you’re seeing here is the result of the universal membership provider which is now calling directly into the Crypto.HashPassword method that we’ve had in System.Web.Helpers for a little while now.

One of the great things about significant portions of ASP.NET now being open sourced is that it’s easier than ever to take a look under the covers. For those that want to see what’s going on, the entire crypto implementation is over on CodePlex.
maybe we can check out that Codeplex to see any diff from yours...http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/89b9166ca722#src/System.Web.Helpers/Crypto.cs
0
 

Author Comment

by:atljarman
ID: 40467600
So I reverted back to the base hashing.  I added this to the code behind for a label.Text to verify that it was truely SHA1.  I feel like i'm losing my mind her but I think slow persistence will pay off.

Membership.HashAlgorithymType.ToString();

Open in new window

0
 
LVL 61

Expert Comment

by:btan
ID: 40468148
the universal membership provider which is now calling directly into the Crypto.HashPassword method, already stated it is the password hash generated with the RFC 2898 algorithm using a 128-bit salt, a 256-bit subkey, and 1000 iterations. The format of the generated hash bytestream is {0x00, salt, subkey}, which is base-64 encoded before it is returned.

And that hashpassword is found in crypto.cs stated it is PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations too. One key comment to note is it stated hashedPassword must be of the format of HashWithPassword (salt + Hash(salt+input).

We probably want to use that hashpassword function...
0
 

Author Comment

by:atljarman
ID: 40468213
See... that's the funny thing.  I ported this over from an ASP .Net 2.0 to 4.0 a couple of years ago.  In the configuration when removing the zetetic security settings, it goes back to SHA1 indicating that it is based on the old model.  Not sure what is going on or how to fix that part.... Right now I did finally... finally... at least be able to create a SHA1 text password with the same salt as the saved password in the database.    I will try to further refine then figure out how to get a better hashing.  Hoping to be able to close this one out soon.
0
 
LVL 61

Expert Comment

by:btan
ID: 40468217
thanks for sharing - as long as it works in first place then thing can be enhance along the way.
0
 
LVL 61

Expert Comment

by:btan
ID: 40546512
thanks for sharing
0
 

Author Closing Comment

by:atljarman
ID: 40554964
I had to go back and start over.  I just kept walking through it until it worked.   Thank you for your time and comments.
0
 
LVL 61

Expert Comment

by:btan
ID: 40555048
thanks!
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
It’s a strangely common occurrence that when you send someone their login details for a system, they can’t get in. This article will help you understand why it happens, and what you can do about it.
Via a live example, show how to extract information from SQL Server on Database, Connection and Server properties
Viewers will learn how to use the SELECT statement in SQL to return specific rows and columns, with various degrees of sorting and limits in place.

743 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

12 Experts available now in Live!

Get 1:1 Help Now