kamagra how much to take

Hashing Password and Password Answers With A Custom Membership Provider

Hashing Password and Password Answers in The Membership Provider
Storing vital user information on your site in plaintext is incredibly poor security practice, and this concept transverse to the concept of membership providers that you use with MOSS / WSS v3. In previous sections, we used a hash method in order to protect our user important user information before placing it into the database. Now, we are going to go over how we are encoding (scrambling) this information, decoding it, and using a salt function that will give us an industry accepted approach to this paradigm.

Encoding the User Password and Password Answer
Recall that during the creation of the user in the previous article we had done the following:

  1. password = this.hashPassword(password);
  2. passwordAnswer = this.hashPassword(passwordAnswer);

The portion that we are going to look at now is hashPassword, which will in turn inherently call GenerateSalt() in order to generate a salt string.

Firstly, we have to setup the hashpassword string. We are going to pass in the the relevant pass value to the string, and declare that it is internal to allow this to cooperate in a private manner.

  1. internal string hashPassword(string pass)

The first thing that we have to do is make sure whether we are passing in a null value, which obviously can’t be encoded or decoded since it has no bit composition. This is done using a simple conditional if loop:

  1. if (pass == null)
  2. {
  3. return null;
  4. }

Following, we have to generate a random string that builds the prefix to the password before we begin the actual hashing process, known as a salt. This is done in order to deter a dictionary attack, although it won’t stop it, it will certainly slow the person doing it down. The reasoning behind it is relatively simple. A malicious user could build up a dictionary of probably passwords, full of entries that could span an arbitrary length, hash it, and then by comparing the hashed entry with the hashed passwords possible exploit a system. The most typical deterrent to this is simply enforcing stronger passwords that adhere to a more complex scheme, however further compensation to this is typically required. Because when we are salting we are prefixing the plaintext password, we are committing both the generated salt as well as the hashed password, and committed it to the custom membership provider user table. If a malicious user following wanted to run a dictionary attack on our SharePoint instance, it would be increasingly difficult since the malicious user would have to hash every password with the salt for every user, which would take a far longer period of time. Generating the salt string takes the form of calling the internal string GenerateSalt() in reference to the current instance of the class:

  1. string saltString = this.GenerateSalt();

The salt generation is a relatively small piece of functionality. We are first going to call a byte array with byte[] and the salt string. We declare a new byte of 0x10 because it is the entry byte length for the salt. For the generation of the random number to gain the benefits talked about in the above section dealing with salts, we are calling the RNG (RandomNumberGenerator)CryptoServiceProvider(), as opposed to the random class since the random class can generate random numbers that are somewhat predictable. Now this is not to say thatRNGCryptoServiceProvider is actually mathematically random, because it isn’t. If we were going to actually implement truly random numbers it would require that we gain parameters from environmental interaction / sources that are unpatternized (those that are based on human oriented behavior). Using the cryptographic Random Number Generator (which, gains its functionality from cryptographic service provider (CSP)) we are able to generate numerics that will provide the least level of collision for our purpose with the leat overhead. Lastly, we have to accepts the crypto byte array as an input argument and return the Base64 encoded string by making a call to Convert.ToBase64String.

  1. internal string GenerateSalt()
  2. {
  3. byte[] saltBuffer = new byte[0x10];
  4. new RNGCryptoServiceProvider().GetBytes(saltBuffer);
  5. return Convert.ToBase64String(saltBuffer);
  6. }
  7. Following, we have to run a condition on the password format to find out the encryption format using the MembershipPasswordFormat enumeration:
  8. if (this.passwordFormat == MembershipPasswordFormat.Clear)
  9. {
  10. return pass;
  11. }
  12. Checking the enrpytion format can be extended in order to check all encrpytion formats even using a simplified switch/case statement:
  13. case "clear":
  14. PasswordFormat = MembershipPasswordFormat.Clear;
  15. break;
  16. case "hashed":
  17. PasswordFormat = MembershipPasswordFormat.Hashed;
  18. break;
  19. case "encrypted":
  20. PasswordFormat = MembershipPasswordFormat.Encrypted;
  21. break;

However in this particular instance we are just testing whether the passwords are being encrypted or not. Following this conditional test, we are going to test whether the passwords are going to be encrypted, and take the appropriate actions. This is done by calling the MembershipPasswordFormat enumeration again however with the encrypted property.

  1. if (this.passwordFormat == MembershipPasswordFormat.Encrypted)
  2. {
  3. byte[] secondary = Convert.FromBase64String(primary);
  4. primary = new byte[secondary.Length + characterEncodingBuffer.Length];
  5. Buffer.BlockCopy(secondary, 0, primary, 0, secondary.Length);
  6. Buffer.BlockCopy(characterEncodingBuffer, 0, primary, secondary.Length, characterEncodingBuffer.Length);

Then out of MembershipProvider pass in the byte array that contains the password to encrypt to the virtual method EncryptPassword. When using EncryptPassword, the password will be encrypted using the settings as they are provided in the machine.config file.

  1. secondary = this.EncryptPassword(primary);
  2. }
  3.  
  4. ]/csharp]
  5.  
  6. As stated in the beginning of this series of articles, if we aren't going to encrypt the password with the machine key, we are to have to use some of the native .NET encryption functionality. In the first part of this, we can see that we are calling the HashAlgorithm.Create property which will identify the algorithm to use to hash the passwords. The algorithm to use is defined by by calling the HashAlgorithmType enumeration that offers the following members:
  7. <ul>
  8.     <li>Md5 - The Message Digest 5 (MD5) hashing algorithm</li>
  9.     <li>None - No hashing algorithm is used</li>
  10.     <li>Sha1 - The Secure Hashing Algorithm (SHA1)</li>
  11. </ul>
  12. [csharp]
  13.  
  14. HashAlgorithm primaryAlgorithm = HashAlgorithm.Create(Membership.HashAlgorithmType);

\

We have to ensure that an algorithm is defined, and if it isn’t we throw an exception that an algorithm has not currently be defined.

  1. if (primaryAlgorithm == null)
  2. {
  3. throw new ProviderException("The mandated hash algorithm is currently not defined.");
  4. }

Checking Users Passwords
For checking the user passwords, we are going to declare a private Boolean, since it will either evaluate to true or false. This is going to take the following parameters:

  • username
  • password

private bool CheckUsersPassword(string username, string password)
Following, we have to run a conditionally loop as to whether either the username or password string is an empty or null value.

  1. {
  2. if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
  3. {
  4. return false;
  5. }

In the second part of this is the first time that are we are seeing the User Information class. This is a seperate, internal class since we are making it available to members of the same assembly.

  1. UserInformation sharepointUserPassword = this.GetUserMembershipByUserName(username);

Deviating slightly, lets look at the UserInformation class. In the UserInformation class we are going to declare the following internal variables:

  • answer
  • membershipUser – We have to declare the MembershipUser class since it will allow us to update and expose all of the relevant membership information
  • password
  1. internal class UserInformation
  2.     {
  3.         internal string answer;
  4.         internal MembershipUser membershipUser;
  5.         internal string password;
  6.  
  7. }

Next, we have to call the internal method UserInformation, that takes the following parameters:

  • membershipUser
  • password
  • answer
  1.        
  2.  
  3. internal UserInformation(MembershipUser membershipUser, string password, string answer)
  4.         {
  5.             this.membershipUser = membershipUser;
  6.             this.password = password;
  7.             this.answer = answer;
  8.         }
  9.     }

Then we simply have to set the parameterized variables to the current instance of the class. As you can see at this point, this is simply a class that provides a layer of abstraction but will be called several times by varying providers and therefore it makes since to place it in something inheritable throughout a number of class files.

Back to checking the passwod information, we are going to run some small checks

  1. bool emptySharePointUserPassword = ((sharepointUserPassword != null) &amp;&amp; sharepointUserPassword.membershipUser.IsApproved) &amp;&amp; !sharepointUserPassword.membershipUser.IsLockedOut;
  2. if (emptySharePointUserPassword)
  3. {
  4. string passwordText = sharepointUserPassword.password;
  5. if (this.PasswordFormat == MembershipPasswordFormat.Encrypted)
  6. {
  7. passwordText = this.DecodePassword(sharepointUserPassword.password);
  8. }
  9. else if (this.PasswordFormat == MembershipPasswordFormat.Hashed)
  10. {
  11. password = this.hashPassword(password);
  12. }
  13. emptySharePointUserPassword = passwordText == password;
  14. if (!emptySharePointUserPassword &amp;&amp; !this.GetFailedAttempts(username, true))
  15. {
  16. this.UpdateMembershipParameter(username, new object[] { "islockedout", DbType.Boolean, true, "lastlockoutdate", DbType.DateTime, DateTime.Now });
  17. }
  18. }
  19. return emptySharePointUserPassword;
  20. }
Share

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>