using Akari.Prototype.Server.Models; using Akari.Prototype.Server.Utils; using Isopoh.Cryptography.Argon2; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Akari.Prototype.Server.Services { public sealed class AuthManager : IAuthManager, IDisposable { public const int AuthKeysLength = 256 / 8; public IEnumerable>> Pairs => _keys; private readonly ILogger _logger; private readonly IKeyManager _keyManager; private IDictionary> _keys; public AuthManager(ILogger logger, IKeyManager keyManager) { _logger = logger; _keyManager = keyManager; _keys = new ConcurrentDictionary>(); } public void Auth(string name, string token) { // Derive key and store it using var key = Security.Argon2idDeriveBytes(token, name, AuthKeysLength, clear: true); SetKey(name, new AesGcm(key.Buffer)); } public bool Remove(string name) { return _keys.Remove(name); } private void SetKey(string name, AesGcm aesGcm) { _logger.LogDebug($"New fingerprint auth: {name}"); if (_keys.TryGetValue(name, out var oldEntry)) { _logger.LogDebug($"Old auth were present for '{name}', clearing it"); oldEntry.Value.Dispose(); } _keys[name] = new TimedEntry(DateTime.Now, aesGcm); _logger.LogDebug($"New auth '{name}' at [{_keys[name].CreationDate}], expires at [{_keys[name].CreationDate + AuthLifetimeService.AuthLifetime}]"); } public void Dispose() { _keys.Clear(); } } }