using System;
using CodeLiturgy.Data.Application.Users;
using CodeLiturgy.Data.Auth.Context.Users;
using Microsoft.AspNetCore.Identity;
namespace BlueWest.Cryptography
{
///
/// Hasher
///
public class Hasher : BaseCryptoItem, IHasher
{
private const int SaltLength = 64;
///
/// CreateHash
///
///
///
///
public string CreateHash(string text, HashAlgorithm algorithm)
{
var salt = CreateRandomString(SaltLength);
return CreateHash(text, salt, algorithm, true);
}
///
/// CreateHash
///
///
///
///
///
public string CreateHash(string text, string saltName, BaseCryptoItem.HashAlgorithm algorithm)
{
return CreateHash(text, saltName, algorithm, false);
}
private string CreateHash(string text, string salt, HashAlgorithm algorithm, bool storeSalt)
{
string hash;
switch (algorithm)
{
case HashAlgorithm.SHA2_512:
var sha2 = new SHA2_512();
hash = sha2.Hash(text, salt, storeSalt);
break;
case HashAlgorithm.SHA3_512:
var sha3 = new SHA2_512();
hash = sha3.Hash(text, salt, storeSalt);
break;
default:
throw new NotImplementedException();
}
return hash;
}
///
/// Check for a matching hash.
///
///
///
///
public bool MatchesHash(string text, string hash)
{
string salt = "";
GetAlgorithm(hash, out var algoAsInt, out _, out _, out salt);
if (!algoAsInt.HasValue) return false;
var hashAlgorithm = (HashAlgorithm) algoAsInt.Value;
var hashed = CreateHash(text, salt, hashAlgorithm, true);
return hashed == hash;
}
///
/// Hash password
///
///
///
///
public string HashPassword(ApplicationUser ApplicationUser, string password)
{
return CreateHash(password, HashAlgorithm.SHA3_512);
}
public PasswordVerificationResult VerifyHashedPassword(ApplicationUser ApplicationUser, string hashedPassword,
string providedPassword)
{
var match = MatchesHash(providedPassword, hashedPassword);
return match ? PasswordVerificationResult.Success : PasswordVerificationResult.Failed;
}
private void GetAlgorithm(string cipherText, out int? algorithm, out int? keyIndex,
out string trimmedCipherText, out string salt)
{
GetAlgorithm(cipherText, out algorithm, out keyIndex, out trimmedCipherText);
if (algorithm.HasValue && trimmedCipherText.Length > SaltLength)
{
salt = trimmedCipherText.Substring(0, SaltLength);
trimmedCipherText = trimmedCipherText.Substring(SaltLength);
}
else
{
salt = null;
}
}
}
}