145 lines
3.7 KiB
C#
145 lines
3.7 KiB
C#
using Akari.Prototype.Server.Options;
|
|
using Akari.Prototype.Server.Utils;
|
|
using Isopoh.Cryptography.Argon2;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text.Json;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Akari.Prototype.Server.Services
|
|
{
|
|
public class FingerprintManager : IFingerprintManager
|
|
{
|
|
public const string FingerprintsPath = "fingerprints.json";
|
|
|
|
public IEnumerable<KeyValuePair<string, string>> FingerprintsHash => _fingerprintsHash;
|
|
|
|
private readonly ILogger<FingerprintManager> _logger;
|
|
private readonly IAuthManager _authManager;
|
|
private readonly AkariPath _akariPath;
|
|
|
|
private IDictionary<string, string> _fingerprintsHash;
|
|
|
|
public FingerprintManager(ILogger<FingerprintManager> logger, IAuthManager authManager, AkariPath akariPath)
|
|
{
|
|
_logger = logger;
|
|
_authManager = authManager;
|
|
_akariPath = akariPath;
|
|
|
|
LoadFingerprints();
|
|
}
|
|
|
|
private void LoadFingerprints()
|
|
{
|
|
var path = _akariPath.GetPath(FingerprintsPath);
|
|
|
|
// Create new
|
|
if (!File.Exists(path))
|
|
{
|
|
_fingerprintsHash = new Dictionary<string, string>();
|
|
|
|
File.WriteAllText(path, JsonSerializer.Serialize(_fingerprintsHash));
|
|
}
|
|
// Load
|
|
else
|
|
{
|
|
_fingerprintsHash = JsonSerializer.Deserialize<IDictionary<string, string>>(File.ReadAllText(path));
|
|
}
|
|
}
|
|
|
|
private void SaveFingerprints()
|
|
{
|
|
var path = _akariPath.GetPath(FingerprintsPath);
|
|
|
|
File.WriteAllText(path, JsonSerializer.Serialize(_fingerprintsHash));
|
|
}
|
|
|
|
public bool Add(string name, string hash)
|
|
{
|
|
if (_fingerprintsHash.TryAdd(name, hash))
|
|
{
|
|
SaveFingerprints();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public bool Contains(string name)
|
|
{
|
|
return _fingerprintsHash.ContainsKey(name);
|
|
}
|
|
|
|
public bool Remove(string name)
|
|
{
|
|
if (_fingerprintsHash.Remove(name))
|
|
{
|
|
SaveFingerprints();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public void Set(string name, string hash)
|
|
{
|
|
_fingerprintsHash[name] = hash;
|
|
|
|
SaveFingerprints();
|
|
}
|
|
|
|
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
|
{
|
|
return _fingerprintsHash.GetEnumerator();
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return GetEnumerator();
|
|
}
|
|
|
|
public void VerifyFingerprint(string name, string token)
|
|
{
|
|
_logger.LogDebug($"Verifying hash for {name}");
|
|
|
|
var handle = GCHandle.Alloc(token, GCHandleType.Pinned);
|
|
|
|
if (!_fingerprintsHash.TryGetValue(name, out var hash))
|
|
{
|
|
_logger.LogDebug($"No fingerprint exist with the name: {name}");
|
|
|
|
handle.Free();
|
|
|
|
return;
|
|
}
|
|
|
|
if (!Argon2.Verify(hash, token))
|
|
{
|
|
_logger.LogDebug($"Token doesn't match stored hash: {name}");
|
|
|
|
handle.Free();
|
|
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
_authManager.Auth(name, token);
|
|
}
|
|
finally
|
|
{
|
|
handle.Free();
|
|
}
|
|
}
|
|
}
|
|
}
|