mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-03-21 09:11:20 +00:00
- NioTSO client isn't needed because we're using RayLib - Added FreeSO's API server to handle most backend operations
77 lines
2.6 KiB
C#
Executable file
77 lines
2.6 KiB
C#
Executable file
using System;
|
|
using System.Collections.Generic;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace FSO.Server.Protocol.Utils
|
|
{
|
|
public class ChallengeResponse
|
|
{
|
|
private static int _salt_byte_length = 320;
|
|
private static int _nonce_byte_length = 32;
|
|
private static RNGCryptoServiceProvider _random_crypt_prov = new RNGCryptoServiceProvider();
|
|
private static Random _random_gen = new Random();
|
|
private static int _min_iteration_count = 4000;
|
|
private static int _max_iteration_count = 5000;
|
|
private const int _sha_output_length = 20;
|
|
|
|
private static byte[] ComputeHMACHash(byte[] data, string secret)
|
|
{
|
|
using (var _hmac_sha_1 = new HMACSHA1(data, true))
|
|
{
|
|
byte[] _hash_bytes = _hmac_sha_1.ComputeHash(Encoding.UTF8.GetBytes(secret));
|
|
return _hash_bytes;
|
|
}
|
|
}
|
|
|
|
public static string AnswerChallenge(string challenge, string secret)
|
|
{
|
|
var components = new Dictionary<string, string>();
|
|
var parts = challenge.Split(',');
|
|
foreach(var part in parts){
|
|
var subParts = part.Split(new char[] { '=' }, 2);
|
|
components.Add(subParts[0], subParts[1]);
|
|
}
|
|
|
|
var iterations = int.Parse(components["i"]);
|
|
var salt = components["s"];
|
|
var salted = Hi(secret, Convert.FromBase64String(salt), iterations);
|
|
|
|
return Convert.ToBase64String(ComputeHMACHash(salted, secret));
|
|
}
|
|
|
|
public static string GetChallenge()
|
|
{
|
|
var numIterations = GetRandomInteger();
|
|
return "i=" + numIterations + ",s=" + Convert.ToBase64String(GetRandomByteArray(_nonce_byte_length));
|
|
}
|
|
|
|
private static byte[] Hi(string password, byte[] salt, int iteration_count)
|
|
{
|
|
Rfc2898DeriveBytes _pdb = new Rfc2898DeriveBytes(password, salt, iteration_count);
|
|
return _pdb.GetBytes(_sha_output_length);
|
|
}
|
|
|
|
private static int GetRandomInteger()
|
|
{
|
|
if (_random_gen == null)
|
|
_random_gen = new Random();
|
|
|
|
int _random_int = _random_gen.Next(_min_iteration_count, _max_iteration_count);
|
|
|
|
if (_random_int < 0)
|
|
_random_int *= -1;
|
|
|
|
return _random_int;
|
|
}
|
|
|
|
private static byte[] GetRandomByteArray(int byte_array_length)
|
|
{
|
|
byte[] _random_byte_array = new byte[byte_array_length];
|
|
|
|
_random_crypt_prov.GetBytes(_random_byte_array);
|
|
|
|
return _random_byte_array;
|
|
}
|
|
}
|
|
}
|