如何调用HashPassword并将用户密码存储到数据库?

How to Call to HashPassword and to store User password to database?

我正在使用 SHA1CryptoServiceProvider() 设置 HashPassword 函数。我的要求包括两种方法:生成我需要帮助的盐和初始化程序。

Salt 与 IV 一起使用,IV 用于在对密码进行哈希处理之前对密码进行加盐,以及要验证的密码。初始化程序采用盐生成器生成的字符串,它将密码和盐混合成一个字符串,并将任何额外字符添加到末尾,然后对混合密码和 returns 值进行哈希处理。

本质上,我需要比较从视图发送的值是否与原始值不同,如果不同,则我需要在创建(新记录)时重新生成哈希和初始化程序。

此控制器操作调用 USERController.Helper 文件中的 HashPassword 函数。

    public ActionResult HashPassword(USERSModel UsersModel)
    {
        USERDto dto = new USERDto();

        if (ModelState.IsValid)
        {
            string hashedPassword = UsersModel.PASSWORD;
            UsersModel.PASSWORD = hashedPassword;
            dto.Updated.Add(hashedPassword);
            dto.Updated.Add("NAME");
            dto.Updated.Add("ID");
            dto.Updated.Add("PASSWORD");
            UsersModel.Updated.SaveChanges();

            ViewBag.Message = "User was added successfully!";
            UsersModel = new USERSModel();

        }
        else
            ViewBag.message = "Error in adding User!";


        return View("USERSSettingsPartial", UsersModel);
    }

 /// <summary>
    /// Called to hash a user password to be stored in the DB.
    /// </summary>
    /// <param name="password">The password to validate.</param>
    /// <param name="salt">The IV used to salt the password before it is hashed.</param>
    /// <param name="errorDesc">Returns an error description if an error occurs.</param>
    /// <returns>Returns the hashed password as a HEX string on success, otherwise returns null.</returns>

        private string HashPassword(string password, byte[] salt, ref string errorDesc)
        {
            try
            {
                byte[] newPassword = Encoding.ASCII.GetBytes(password.ToUpper());
                if (salt != null && salt.Length > 0)
                {
                    int count = (salt.Length < newPassword.Length) ? salt.Length : newPassword.Length;
                    byte[] temp = new byte[salt.Length + newPassword.Length];
                    for (int index = 0; index < count; index++)
                    {
                        temp[index * 2] = newPassword[index];
                        temp[index * 2 + 1] = salt[index];
                    }
                    if (count == salt.Length && count < newPassword.Length)
                        Buffer.BlockCopy(newPassword, count, temp, count * 2, newPassword.Length - count);
                    else if (count == newPassword.Length && count < salt.Length)
                        Buffer.BlockCopy(salt, count, temp, count * 2, salt.Length - count);

                    newPassword = temp;
                }
                using (var hash = new System.Security.Cryptography.SHA1CryptoServiceProvider())
                {
                    hash.ComputeHash(newPassword);
                    return this.GetHexStringFromBytes(hash.Hash);
                }
            }
            catch (Exception Ex)
            {
                errorDesc = Ex.Message;
                if (Ex.InnerException != null) errorDesc = string.Format("{0}\r\n{1}", errorDesc, Ex.InnerException.Message);
            }
            return null;
        }

        /// <summary>
        /// called to convert byte data into hexidecimal string were each byte is represented as two hexidecimal characters.
        /// </summary>
        /// <param name="data">Byte data to convert.</param>
        /// <returns>A hexidecimal string version of the data.</returns>
        private string GetHexStringFromBytes(byte[] data)
        {
            if (data == null || data.Length == 0) return string.Empty;

            StringBuilder sbHex = new StringBuilder();
            for (int index = 0; index < data.Length; index++) sbHex.AppendFormat(null, "{0:X2}", data[index]);

            return sbHex.ToString();
        }

        /// <summary>
        /// called to convert hexadecimal string into byte data were two hexadecimal characters are converted into a byte.
        /// </summary>
        /// <param name="hexString">A hexidecimal string to convert</param>
        /// <returns>The converted byte data.</returns>
        private byte[] GetBytesFromHexString(string hexString)
        {
            if (string.IsNullOrEmpty(hexString)) return null;

            byte[] data = new byte[hexString.Length / 2];
            for (int index = 0; index < data.Length; index++)
            {
                data[index] = byte.Parse(hexString.Substring(index * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            return data;
        }  

这是我第一次做这样的项目,所以我没有任何输出。只需要示例就可以更好地理解。

基本上需要在服务中有一个控制器,其中此 class 将创建盐并从控制器助手 class 调用。我所做的是在服务器端设置 Initializer,然后将代码添加到 USERS 服务控制器创建 IHttpActionResult 来设置 salt 和密码。您永远不想将密码存储在数据库中,总是希望对它们进行哈希处理。
我在 USERS 的服务控制器中创建了一个请求,传入 DTO,用于创建新记录,返回包含查询结果的对象(如果有),否则 returns 未找到或内部服务器错误消息。在此方法中,Salt 被调用:

public IHttpActionResult Create([FromBody]USERDto dto)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        try
        {
            byte[] saltValue;
            string error = string.Empty;

            saltValue = GenerateSalt();
            dto.INITIALIZER = GetHexStringFromBytes(saltValue);
            dto.PASSWORD = HashPassword(dto.PASSWORD, saltValue, ref error);

            USERDto created = USERSProcessor.Create(dto);
            if (created == null)
            {
                return NotFound();
            }
            return Ok(created);
        }
        catch (Exception ex)
        {
            LogUtility.LogError(ex);
            return InternalServerError(ex);
        }
    }

然后(为了不让控制器混乱)我创建了一个控制器助手 class 并添加了这段代码来实现散列盐方法,其中 USERSController 调用要存储在数据库中的散列密码,以及因为调用 dto.INITIALIZER 将字节数据转换为十六进制字符串,其中每个字节表示为两个十六进制字符:

partial class USERSController
{    
    /// <summary>
    /// Called to generate salt byte array.
    /// </summary>
    /// <returns>The generated salt byte array.</returns>
    public static byte[] GenerateSalt()
    {
        byte[] iv;
        using (var alg = new AesCryptoServiceProvider())
        {
            alg.BlockSize = 128; //block size is 8bytes, which is the the size of the IV generated.
            alg.KeySize = 256; //key size is 32bytes
            alg.GenerateIV();
            iv = alg.IV;
        }

        return iv;
    }


    /// <summary>
    /// Called to hash a user password to be stored in DB.
    /// </summary>
    /// <param name="password">The password to validate.</param>
    /// <param name="salt">The IV used to salt the password before it is hashed.</param>
    /// <param name="errorDesc">Returns an error description if an error occurs.</param>
    /// <returns>Returns the hashed password as a HEX string on success, otherwise returns null.</returns>
    private static string HashPassword(string password, byte[] salt, ref string errorDesc)
    {
        try
        {
            byte[] newPassword = Encoding.ASCII.GetBytes(password.ToUpper());
            if (salt != null && salt.Length > 0)
            {
                int count = (salt.Length < newPassword.Length) ? salt.Length : newPassword.Length;
                byte[] temp = new byte[salt.Length + newPassword.Length];
                for (int index = 0; index < count; index++)
                {
                    temp[index * 2] = newPassword[index];
                    temp[index * 2 + 1] = salt[index];
                }
                if (count == salt.Length && count < newPassword.Length)
                    Buffer.BlockCopy(newPassword, count, temp, count * 2, newPassword.Length - count);
                else if (count == newPassword.Length && count < salt.Length)
                    Buffer.BlockCopy(salt, count, temp, count * 2, salt.Length - count);

                newPassword = temp;
            }
            using (var hash = new System.Security.Cryptography.SHA1CryptoServiceProvider())
            {
                hash.ComputeHash(newPassword);
                return GetHexStringFromBytes(hash.Hash);
            }
        }
        catch (Exception Ex)
        {
            errorDesc = Ex.Message;
            if (Ex.InnerException != null) errorDesc = string.Format("{0}\r\n{1}", errorDesc, Ex.InnerException.Message);
        }
        return null;
    }

    /// <summary>
    /// called to convert byte data into hexidecimal string were each byte is represented as two hexidecimal characters.
    /// </summary>
    /// <param name="data">Byte data to convert.</param>
    /// <returns>A hexidecimal string version of the data.</returns>
    private static string GetHexStringFromBytes(byte[] data)
    {
        if (data == null || data.Length == 0) return string.Empty;

        StringBuilder sbHex = new StringBuilder();
        for (int index = 0; index < data.Length; index++) sbHex.AppendFormat(null, "{0:X2}", data[index]);

        return sbHex.ToString();
    }

    /// <summary>
    /// called to convert hexidecimal string into byte data were two hexidecimal characters are converted into a byte.
    /// </summary>
    /// <param name="hexString">A hexidecimal string to convert</param>
    /// <returns>The converted byte data.</returns>
    private static byte[] GetBytesFromHexString(string hexString)
    {
        if (string.IsNullOrEmpty(hexString)) return null;

        byte[] data = new byte[hexString.Length / 2];
        for (int index = 0; index < data.Length; index++)
        {
            data[index] = byte.Parse(hexString.Substring(index * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
        }
        return data;
    }       

}