using Isopoh.Cryptography.Argon2;
using Isopoh.Cryptography.SecureArray;
using System.Security.Cryptography;
using System.Text;
using Chaos.NaCl;
namespace Hasher
{
///
/// A utility class for generating and verifying Argon2 hashes.
///
public static class Argon2dHasher
{
private static readonly RandomNumberGenerator Rng = RandomNumberGenerator.Create();
///
/// Generates an Argon2 hash for the given password and salt.
///
/// The password to hash.
/// A random salt to use for the hash. If null, a new 16-byte salt will be generated.
/// The generated Argon2 hash as a string.
public static string GenerateArgon2Hash(string password, byte[]? salt)
{
if (salt == null)
{
salt = new byte[16];
}
byte[] pwBytes = Encoding.UTF8.GetBytes(password);
// Generate a random salt
Rng.GetBytes(salt);
var config = new Argon2Config
{
Type = Argon2Type.DataIndependentAddressing,
Version = Argon2Version.Nineteen,
TimeCost = 6,
Lanes = 3,
Threads = Environment.ProcessorCount - 1, // higher than "Lanes" doesn't help (or hurt)
Password = pwBytes,
Salt = salt,
};
var argon2 = new Argon2(config);
string hashString;
using(SecureArray hashA = argon2.Hash())
{
hashString = config.EncodeString(hashA.Buffer);
}
return hashString;
}
///
/// Verifies that a given password matches an Argon2 hash.
///
/// The password to check.
/// The Argon2 hash to check against.
/// True if the password matches the hash, false otherwise.
public static bool VerifyArgon2Hash(string password, string hash)
{
byte[] pwBytes = Encoding.UTF8.GetBytes(password);
var valid = Argon2.Verify(hash, pwBytes);
return valid;
}
}
///
/// The FingerPrinter class provides methods to generate and hash fingerprints.
///
public class FingerPrinter
{
///
/// Helper function to generate a random string of a given length.
///
/// The length of the string to generate.
/// A random string of the specified length.
private static string GetRandomString(int length)
{
var r = new Random();
return new String(Enumerable.Range(0, length).Select(n => (Char)(r.Next(32, 127))).ToArray());
}
///
/// Helper function to hash a fingerprint using SHA-256.
///
/// The fingerprint to hash.
/// The SHA-256 hash of the input fingerprint as a base64-encoded string.
private static string HashFingerprint(string fingerprint)
{
using var sha256 = SHA256.Create();
var hashedFingerprint = sha256.ComputeHash(Encoding.UTF8.GetBytes(fingerprint));
return Convert.ToBase64String(hashedFingerprint);
}
///
/// Returns an array containing a randomly generated plain text fingerprint and its hashed value.
///
/// The length of the plain text fingerprint to generate (default is 32).
/// An array of two strings: the plain text fingerprint and its hashed value.
public static string[] GetFingerprintSet(int length = 32)
{
string plainText = GetRandomString(length);
string hashed = HashFingerprint(plainText);
return new string[] { plainText, hashed };
}
///
/// Validates whether the specified fingerprint matches the provided hashed fingerprint using SHA256 encryption.
///
/// The fingerprint string to be validated.
/// The hashed fingerprint to be compared against the fingerprint.
/// Returns a boolean value indicating whether the fingerprint and its hash match or not.
public static bool ValidateFingerpint(string fingerprint, string fpHash)
{
using var sha256 = SHA256.Create();
var newFpHash = sha256.ComputeHash(Encoding.UTF8.GetBytes(fingerprint));
return Convert.ToBase64String(newFpHash) == fpHash ;
}
}
public class KeyHelper
{
private static byte[] FromBase64String(string input)
{
return Convert.FromBase64String(input);
}
public static bool validateSignature(string signature, string message, string publicKey)
{
return Ed25519.Verify(FromBase64String(signature), Encoding.UTF8.GetBytes(message), FromBase64String(publicKey));
}
}
}