我正在使用SHA1CryptoServiceProvider()设置HashPassword函数。我的需求包括两种方法:生成需要帮助的salt和初始化器。
Salt与IV结合使用,IV用于在对密码进行哈希处理之前对其加盐,并验证密码。初始化程序使用salt生成器生成的字符串,将密码和salt混合成一个字符串,并在末尾添加任何多余的字符,然后对混合后的密码进行哈希处理并返回值。
本质上,我需要比较从视图发送的值是否不同于原始值,如果确实不同,则需要在create(new record)上重新生成哈希和初始化程序。
该控制器操作调用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;
}
这是我第一次处理类似这样的项目,因此我没有任何输出。只需要示例以更好地理解。
答案 0 :(得分:0)
基本上需要在Service中有一个Controller,该类将在其中创建盐并从Controller Helper类中调用。我所做的是在服务器端设置了Initializer,然后在其中向USERS服务控制器中添加了代码,从而创建了IHttpActionResult来设置盐和密码。您从不希望将密码存储在数据库中,而总是希望对它们进行哈希处理。
我在传递DTO的USERS的服务控制器中创建了一个请求,该请求用于创建新记录,返回包含查询结果(如果有)的对象,否则返回未找到或内部服务器错误消息。在此方法中,盐被称为:
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);
}
}
然后(为了不使控制器混乱),我创建了一个控制器帮助器类并添加了此代码以实现哈希盐方法,其中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;
}
}