83 lines
2.1 KiB
C#
83 lines
2.1 KiB
C#
using System;
|
|
using static StellaOps.Localization.T;
|
|
|
|
namespace StellaOps.Cryptography;
|
|
|
|
/// <summary>
|
|
/// Supported password hashing algorithms.
|
|
/// </summary>
|
|
public enum PasswordHashAlgorithm
|
|
{
|
|
Argon2id,
|
|
Pbkdf2
|
|
}
|
|
|
|
/// <summary>
|
|
/// Options describing password hashing requirements.
|
|
/// Values follow OWASP baseline guidance by default.
|
|
/// </summary>
|
|
public sealed record PasswordHashOptions
|
|
{
|
|
/// <summary>
|
|
/// Algorithm to use when hashing new passwords.
|
|
/// </summary>
|
|
public PasswordHashAlgorithm Algorithm { get; init; } = PasswordHashAlgorithm.Argon2id;
|
|
|
|
/// <summary>
|
|
/// Memory cost in KiB (default 19 MiB).
|
|
/// </summary>
|
|
public int MemorySizeInKib { get; init; } = 19 * 1024;
|
|
|
|
/// <summary>
|
|
/// Iteration count / time cost.
|
|
/// </summary>
|
|
public int Iterations { get; init; } = 2;
|
|
|
|
/// <summary>
|
|
/// Parallelism / degree of concurrency.
|
|
/// </summary>
|
|
public int Parallelism { get; init; } = 1;
|
|
|
|
/// <summary>
|
|
/// Validates the option values and throws when invalid.
|
|
/// </summary>
|
|
public void Validate()
|
|
{
|
|
if (MemorySizeInKib <= 0)
|
|
{
|
|
throw new InvalidOperationException(_t("crypto.password.memory_cost_invalid"));
|
|
}
|
|
|
|
if (Iterations <= 0)
|
|
{
|
|
throw new InvalidOperationException(_t("crypto.password.iterations_invalid"));
|
|
}
|
|
|
|
if (Parallelism <= 0)
|
|
{
|
|
throw new InvalidOperationException(_t("crypto.password.parallelism_invalid"));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Abstraction for password hashing implementations.
|
|
/// </summary>
|
|
public interface IPasswordHasher
|
|
{
|
|
/// <summary>
|
|
/// Produces an encoded hash for the supplied password.
|
|
/// </summary>
|
|
string Hash(string password, PasswordHashOptions options);
|
|
|
|
/// <summary>
|
|
/// Verifies the supplied password against a stored hash.
|
|
/// </summary>
|
|
bool Verify(string password, string encodedHash);
|
|
|
|
/// <summary>
|
|
/// Detects when an existing encoded hash no longer satisfies the desired options.
|
|
/// </summary>
|
|
bool NeedsRehash(string encodedHash, PasswordHashOptions desired);
|
|
}
|