gpt4 book ai didi

c# - 身份框架和自定义密码哈希器

转载 作者:行者123 更新时间:2023-11-30 12:41:24 27 4
gpt4 key购买 nike

我已将身份框架添加到我的 WebApi 并遵循此处列出的步骤:

http://bitoftech.net/2015/01/21/asp-net-identity-2-with-asp-net-web-api-2-accounts-management/

所有这些都运行良好。我遇到的问题是,我的客户有另一个系统,API 与之集成(以收集数据)并且有自己的登录方法。因此,考虑到这一点,我的客户要求我使用 CustomPasswordHasher 来加密和解密密码。他们想要做的是能够获得密码哈希并将其转换为实际密码,以便他们可以使用它登录旧系统(两个密码/帐户将相同)。我知道这很不正常,但我别无选择。

我的问题是,这有多容易做到?我发现了一些关于如何创建自定义密码哈希器的主题,但没有一个主题告诉我如何从哈希密码中实际获取密码,它们只展示了如何比较。

目前我有这个:

public class PasswordHasher : IPasswordHasher
{
private readonly int _saltSize;
private readonly int _bytesRequired;
private readonly int _iterations;

public PasswordHasher()
{
this._saltSize = 128 / 8;
this._bytesRequired = 32;
this._iterations = 1000;
}

public string HashPassword(string password)
{

// Create our defaults
var array = new byte[1 + this._saltSize + this._bytesRequired];

// Try to hash our password
using (var pbkdf2 = new Rfc2898DeriveBytes(password, this._saltSize, this._iterations))
{
var salt = pbkdf2.Salt;
Buffer.BlockCopy(salt, 0, array, 1, this._saltSize);

var bytes = pbkdf2.GetBytes(this._bytesRequired);
Buffer.BlockCopy(bytes, 0, array, this._saltSize + 1, this._bytesRequired);
}

// Return the password base64 encoded
return Convert.ToBase64String(array);
}

public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{

// Throw an error if any of our passwords are null
ThrowIf.ArgumentIsNull(() => hashedPassword, () => providedPassword);

// Get our decoded hash
var decodedHashedPassword = Convert.FromBase64String(hashedPassword);

// If our password length is 0, return an error
if (decodedHashedPassword.Length == 0)
return PasswordVerificationResult.Failed;

var t = decodedHashedPassword[0];

// Do a switch
switch (decodedHashedPassword[0])
{
case 0x00:
return PasswordVerificationResult.Success;

default:
return PasswordVerificationResult.Failed;
}
}

private bool VerifyHashedPassword(byte[] hashedPassword, string password)
{

// If we are not matching the original byte length, then we do not match
if (hashedPassword.Length != 1 + this._saltSize + this._bytesRequired)
return false;

//// Get our salt
//var salt = pbkdf2.Salt;
//Buffer.BlockCopy(salt, 0, array, 1, this._saltSize);

//var bytes = pbkdf2.GetBytes(this._bytesRequired);
//Buffer.BlockCopy(bytes, 0, array, this._saltSize + 1, this._bytesRequired);

return true;
}
}

如果我真的想要,我可以这样做:

public class PasswordHasher : IPasswordHasher
{
public string HashPassword(string password)
{
// Do no hashing
return password;
}

public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{

// Throw an error if any of our passwords are null
ThrowIf.ArgumentIsNull(() => hashedPassword, () => providedPassword);

// Just check if the two values are the same
if (hashedPassword.Equals(providedPassword))
return PasswordVerificationResult.Success;

// Fallback
return PasswordVerificationResult.Failed;
}
}

但这太疯狂了,因为所有密码都将以纯文本形式存储。一定有办法在我打电话时“加密”密码并“解密”它吗?

最佳答案

所以,我尽量保证安全。这就是我所做的。我创建了一个新的提供者:

public class AdvancedEncryptionStandardProvider
{

// Private properties
private readonly ICryptoTransform _encryptor, _decryptor;
private UTF8Encoding _encoder;

/// <summary>
/// Default constructor
/// </summary>
/// <param name="key">Our shared key</param>
/// <param name="secret">Our secret</param>
public AdvancedEncryptionStandardProvider(string key, string secret)
{

// Create our encoder
this._encoder = new UTF8Encoding();

// Get our bytes
var _key = _encoder.GetBytes(key);
var _secret = _encoder.GetBytes(secret);

// Create our encryptor and decryptor
var managedAlgorithm = new RijndaelManaged();
managedAlgorithm.BlockSize = 128;
managedAlgorithm.KeySize = 128;

this._encryptor = managedAlgorithm.CreateEncryptor(_key, _secret);
this._decryptor = managedAlgorithm.CreateDecryptor(_key, _secret);
}

/// <summary>
/// Encrypt a string
/// </summary>
/// <param name="unencrypted">The un-encrypted string</param>
/// <returns></returns>
public string Encrypt(string unencrypted)
{
return Convert.ToBase64String(Encrypt(this._encoder.GetBytes(unencrypted)));
}

/// <summary>
/// Decrypt a string
/// </summary>
/// <param name="encrypted">The encrypted string</param>
/// <returns></returns>
public string Decrypt(string encrypted)
{
return this._encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
}

/// <summary>
/// Encrypt some bytes
/// </summary>
/// <param name="buffer">The bytes to encrypt</param>
/// <returns></returns>
public byte[] Encrypt(byte[] buffer)
{
return Transform(buffer, this._encryptor);
}

/// <summary>
/// Decrypt some bytes
/// </summary>
/// <param name="buffer">The bytes to decrypt</param>
/// <returns></returns>
public byte[] Decrypt(byte[] buffer)
{
return Transform(buffer, this._decryptor);
}

/// <summary>
/// Writes bytes to memory
/// </summary>
/// <param name="buffer">The bytes</param>
/// <param name="transform"></param>
/// <returns></returns>
protected byte[] Transform(byte[] buffer, ICryptoTransform transform)
{

// Create our memory stream
var stream = new MemoryStream();

// Write our bytes to the stream
using (var cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
}

// Retrun the stream as an array
return stream.ToArray();
}
}

然后我的PasswordHasher,我改成了这样:

public class PasswordHasher : IPasswordHasher
{

// Private properties
private readonly AdvancedEncryptionStandardProvider _provider;

public PasswordHasher(AdvancedEncryptionStandardProvider provider)
{
this._provider = provider;
}

public string HashPassword(string password)
{
// Do no hashing
return this._provider.Encrypt(password);
}

public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{

// Throw an error if any of our passwords are null
ThrowIf.ArgumentIsNull(() => hashedPassword, () => providedPassword);

// Just check if the two values are the same
if (hashedPassword.Equals(this.HashPassword(providedPassword)))
return PasswordVerificationResult.Success;

// Fallback
return PasswordVerificationResult.Failed;
}
}

要使用此 PasswordHasher,您可以像这样调用它:

var passwordHasher = new PasswordHasher(new AdvancedEncryptionStandardProvider(ConfigurationManager.AppSettings["as:key"], ConfigurationManager.AppSettings["as:secret"]));

这似乎满足了我的条件。请让我知道是否存在安全风险!

关于c# - 身份框架和自定义密码哈希器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37702707/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com