Monday, 18 March 2013

Password Salt and Hash Cipher values in C#



public static class SecurityManager
    {
        #region "-- Private --"

        #region "-- Variables --"

        //-- The following constants may be changed without breaking existing hashes.
        public const int SALT_BYTES = 24;
        public const int HASH_BYTES = 24;
        public const int PBKDF2_ITERATIONS = 1000;

        public const int ITERATION_INDEX = 0;
        public const int SALT_INDEX = 1;
        public const int PBKDF2_INDEX = 2;

        #endregion "-- Variables --"

        #region "-- Methods --"
       
        private static string GeByteArrayToString(byte[] inputArray)
        {
            StringBuilder RetVal = new StringBuilder("");

            for (int i = 0; i < inputArray.Length; i++)
            {
                RetVal.Append(inputArray[i].ToString("X2"));
            }

            return RetVal.ToString();
        }

        /// <summary>
        /// Computes the PBKDF2-SHA1 hash of a password.
        /// </summary>
        /// <param name="password">The password to hash.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="iterations">The PBKDF2 iteration count.</param>
        /// <param name="outputBytes">The length of the hash to generate, in bytes.</param>
        /// <returns>A hash of the password.</returns>
        private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
        {
            Rfc2898DeriveBytes Pbkdf2 = new Rfc2898DeriveBytes(password, salt);
            Pbkdf2.IterationCount = iterations;
            return Pbkdf2.GetBytes(outputBytes);
        }

        #endregion "-- Methods --"

        #endregion "-- Private --"

        #region "-- public --"

        #region "-- Methods --"

        /// <summary>
        /// Sets authentication cookie using form authentication ticket
        /// </summary>
        /// <param name="userNid"></param>
        /// <param name="role"></param>
        public static void SetAuthentication(string userNid, string role)
        {
            FormsAuthenticationTicket AuthTicket = new FormsAuthenticationTicket(
              1,
              userNid,  //user id
              DateTime.Now,
              DateTime.Now.AddMinutes(200),  // expiry
              false,  //do not remember
              role,
              "/");
            HttpCookie Cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
                                               FormsAuthentication.Encrypt(AuthTicket));
            HttpContext.Current.Response.Cookies.Add(Cookie);
        }

        /// <summary>
        /// Returns salt for cryptography
        /// </summary>
        /// <returns></returns>
        public static string GetSalt()
        {
            string RetVal = string.Empty;
            RNGCryptoServiceProvider Csprng = new RNGCryptoServiceProvider();
            byte[] Salt = new byte[SALT_BYTES];
            Csprng.GetBytes(Salt);

            return Convert.ToBase64String(Salt);
        }

        /// <summary>
        /// Returns temp password
        /// </summary>
        /// <returns></returns>
        public static string GetTempPassword()
        {
            return System.Web.Security.Membership.GeneratePassword(8, 3).Replace(".", "-").Replace(@"\", "#");
        }

        /// <summary>
        /// Returns salted hash value
        /// </summary>
        /// <param name="plainPassword"></param>
        /// <param name="salt"></param>
        /// <returns></returns>
        public static string GetSaltedHashValue(string plainPassword, string salt)
        {
            string RetVal = string.Empty;
            byte[] SaltArr = new byte[SALT_BYTES];           

            // Hash the password and encode the parameters

            if (!string.IsNullOrEmpty(plainPassword) && !string.IsNullOrEmpty(salt))
            {
                SaltArr = Convert.FromBase64String(salt);

                byte[] Hash = PBKDF2(plainPassword, SaltArr, PBKDF2_ITERATIONS, HASH_BYTES);

                RetVal = PBKDF2_ITERATIONS + ":" + salt + ":" + Convert.ToBase64String(Hash);
            }

            return RetVal;
        }
       
        /// <summary>
        /// Validates a password/text given a hash of the correct one.
        /// </summary>
        /// <param name="passwordOrText">The password/text to check.</param>
        /// <param name="hashValue">A hash of the correct password/text.</param>
        /// <param name="salt"></param>
        /// <returns>True if the password is correct. False otherwise.</returns>
        public static bool ValidatePasswordOrText(string passwordOrText, string hashValue, string salt)
        {
            bool RetVal = false;
            if (string.IsNullOrEmpty(passwordOrText) || string.IsNullOrEmpty(hashValue) || string.IsNullOrEmpty(salt))
            {
                RetVal = false;
            }
            // compare hash value
            else if (String.Equals(GetSaltedHashValue(passwordOrText, salt), hashValue))
            {
                RetVal = true;
            }
            return RetVal;
        }

        #endregion "-- Methods --"

        #endregion "-- public --"
    }

No comments:

Post a Comment