mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-03-15 14:51:21 +00:00
- NioTSO client isn't needed because we're using RayLib - Added FreeSO's API server to handle most backend operations
103 lines
2.9 KiB
C#
Executable file
103 lines
2.9 KiB
C#
Executable file
using System;
|
|
using System.Linq;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace FSO.Server.Common
|
|
{
|
|
public class PasswordHasher
|
|
{
|
|
public static PasswordHash Hash(string password)
|
|
{
|
|
return Hash(password, "Rfc2898");
|
|
}
|
|
|
|
public static PasswordHash Hash(string password, string scheme)
|
|
{
|
|
var schemeImpl = GetScheme(scheme);
|
|
return schemeImpl.Hash(password);
|
|
}
|
|
|
|
public static bool Verify(string password, PasswordHash hash)
|
|
{
|
|
return Verify(password, hash, "Rfc2898");
|
|
}
|
|
|
|
public static bool Verify(string password, PasswordHash hash, string scheme)
|
|
{
|
|
var schemeImpl = GetScheme(scheme);
|
|
return schemeImpl.Verify(password, hash);
|
|
}
|
|
|
|
private static IPasswordHashScheme GetScheme(string scheme)
|
|
{
|
|
switch (scheme)
|
|
{
|
|
case "Rfc2898":
|
|
return new DefaultPasswordHashScheme();
|
|
}
|
|
|
|
throw new Exception("Unknown password hash scheme: " + scheme);
|
|
}
|
|
}
|
|
|
|
public class PasswordHash
|
|
{
|
|
public byte[] data;
|
|
public string scheme;
|
|
}
|
|
|
|
public class DefaultPasswordHashScheme : IPasswordHashScheme
|
|
{
|
|
public PasswordHash Hash(string password)
|
|
{
|
|
var salt_input = GetStrongRandomBytes(16);
|
|
|
|
|
|
return new PasswordHash()
|
|
{
|
|
scheme = "Rfc2898",
|
|
data = Hash(salt_input, password)
|
|
};
|
|
}
|
|
|
|
private byte[] Hash(byte[] salt_input, string password)
|
|
{
|
|
var hasher = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetBytes(password), salt_input, 1000);
|
|
var hash = hasher.GetBytes(64);
|
|
|
|
//Encode the salt + hash together
|
|
var result = new byte[1 + 16 + hash.Length];
|
|
result[0] = (byte)16;
|
|
Array.Copy(salt_input, 0, result, 1, salt_input.Length);
|
|
Array.Copy(hash, 0, result, salt_input.Length + 1, hash.Length);
|
|
|
|
return result;
|
|
}
|
|
|
|
public bool Verify(string password, PasswordHash hash)
|
|
{
|
|
var salt_length = hash.data[0];
|
|
var salt_input = new byte[salt_length];
|
|
Array.Copy(hash.data, 1, salt_input, 0, salt_length);
|
|
|
|
var expected = Hash(salt_input, password);
|
|
return expected.SequenceEqual(hash.data);
|
|
}
|
|
|
|
private byte[] GetStrongRandomBytes(int numBytes)
|
|
{
|
|
var random_bytes = new byte[numBytes];
|
|
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
|
|
{
|
|
rngCsp.GetBytes(random_bytes);
|
|
}
|
|
return random_bytes;
|
|
}
|
|
}
|
|
|
|
public interface IPasswordHashScheme
|
|
{
|
|
PasswordHash Hash(string password);
|
|
bool Verify(string password, PasswordHash hash);
|
|
}
|
|
}
|