From 7a1f2946fcb92484967169992037562710045038 Mon Sep 17 00:00:00 2001 From: Eveldee Date: Sat, 5 Jun 2021 21:36:01 +0200 Subject: [PATCH] Add IApplicationManager --- Akari.Prototype.Server/Models/Application.cs | 9 ++ .../Services/ApplicationsManager.cs | 148 ++++++++++++++++++ .../Services/AuthManager.cs | 6 +- .../Services/FingerprintManager.cs | 2 +- .../Services/IApplicationsManager.cs | 18 +++ .../Services/IAuthManager.cs | 2 + Akari.Prototype.Server/Startup.cs | 1 + 7 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 Akari.Prototype.Server/Models/Application.cs create mode 100644 Akari.Prototype.Server/Services/ApplicationsManager.cs create mode 100644 Akari.Prototype.Server/Services/IApplicationsManager.cs diff --git a/Akari.Prototype.Server/Models/Application.cs b/Akari.Prototype.Server/Models/Application.cs new file mode 100644 index 0000000..92ff7f3 --- /dev/null +++ b/Akari.Prototype.Server/Models/Application.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Akari.Prototype.Server.Models +{ + public record Application(string Name, string TokenHash, IList Fingerprints); +} diff --git a/Akari.Prototype.Server/Services/ApplicationsManager.cs b/Akari.Prototype.Server/Services/ApplicationsManager.cs new file mode 100644 index 0000000..411bfc0 --- /dev/null +++ b/Akari.Prototype.Server/Services/ApplicationsManager.cs @@ -0,0 +1,148 @@ +using Akari.Prototype.Server.Models; +using Akari.Prototype.Server.Utils; +using Isopoh.Cryptography.Argon2; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text.Json; +using System.Threading.Tasks; + +namespace Akari.Prototype.Server.Services +{ + public class ApplicationsManager : IApplicationsManager + { + public const string ApplicationsPath = "applications.json"; + public const int ApplicationTokenLength = 18; + + private readonly ILogger _logger; + private readonly IKeyManager _keyManager; + private readonly IAuthManager _authManager; + private readonly AkariPath _akariPath; + + private IDictionary _applications; + + public ApplicationsManager(ILogger logger, IKeyManager keyManager, IAuthManager authManager, AkariPath akariPath) + { + _logger = logger; + _keyManager = keyManager; + _authManager = authManager; + _akariPath = akariPath; + + LoadApplications(); + } + + private void LoadApplications() + { + var path = _akariPath.GetPath(ApplicationsPath); + + if (!File.Exists(path)) + { + _applications = new Dictionary(); + + File.WriteAllText(path, JsonSerializer.Serialize(_applications.Values)); + } + else + { + _applications = JsonSerializer.Deserialize>(File.ReadAllText(path)).ToDictionary(a => a.Name); + } + } + + private void SaveApplications() + { + var path = _akariPath.GetPath(ApplicationsPath); + + File.WriteAllText(path, JsonSerializer.Serialize(_applications.Values)); + } + + public bool AddFingerprint(string applicationName, string applicationToken, string fingerprintName, string masterPassword) + { + if (!VerifyToken(applicationName, applicationToken)) + { + _logger.LogDebug($"Wrong token provided for {applicationName}"); + + return false; + } + + // Verify master password + + // Try get fingerprint key + if (!_authManager.TryGetKey(fingerprintName, out var key)) + { + _logger.LogDebug($"Fingerprint '{fingerprintName}' has not been auth"); + + return false; + } + + // Encrypt key + //_keyManager.AddFingerprint(applicationName, fingerprintName, key, masterPassword); + + _applications[applicationName].Fingerprints.Add(fingerprintName); + + SaveApplications(); + + return true; + } + + private bool VerifyToken(string applicationName, string token) + { + if (!_applications.TryGetValue(applicationName, out var application)) + { + return false; + } + + return Argon2.Verify(application.TokenHash, Convert.FromBase64String(token)); + } + + public bool TryCreate(string applicationName, out string token) + { + if (_applications.ContainsKey(applicationName)) + { + _logger.LogDebug($"Can't create '{applicationName}' as it already exists"); + + token = null; + + return false; + } + + var tokenData = new byte[ApplicationTokenLength]; + + RandomNumberGenerator.Fill(tokenData); + + var hash = Security.NewArgon2idHash(tokenData); + + var application = new Application(applicationName, hash, new List()); + + _applications[applicationName] = application; + + token = Convert.ToBase64String(tokenData); + + SaveApplications(); + + _logger.LogDebug($"Application '{applicationName}' created"); + + return true; + } + + public bool TryRetrieveKey(string applicationName, string token, out AesGcm key) + { + key = null; + + if (!_applications.TryGetValue(applicationName, out var application)) + { + return false; + } + + if (!VerifyToken(applicationName, token)) + { + return false; + } + + //key = _authManager.Retrieve(applicationName); + + return true; + } + } +} diff --git a/Akari.Prototype.Server/Services/AuthManager.cs b/Akari.Prototype.Server/Services/AuthManager.cs index 941372c..0f6217f 100644 --- a/Akari.Prototype.Server/Services/AuthManager.cs +++ b/Akari.Prototype.Server/Services/AuthManager.cs @@ -25,16 +25,14 @@ namespace Akari.Prototype.Server.Services public IEnumerable>> Pairs => _keys; private readonly ILogger _logger; - private readonly IKeyManager _keyManager; private readonly AkariPath _akariPath; private IDictionary> _keys; private IDictionary _salts; - public AuthManager(ILogger logger, IKeyManager keyManager, AkariPath akariPath) + public AuthManager(ILogger logger, AkariPath akariPath) { _logger = logger; - _keyManager = keyManager; _akariPath = akariPath; _keys = new ConcurrentDictionary>(); @@ -56,7 +54,7 @@ namespace Akari.Prototype.Server.Services // Load else { - _salts = JsonSerializer.Deserialize>(File.ReadAllText(path)); + _salts = JsonSerializer.Deserialize>(File.ReadAllText(path)); } } diff --git a/Akari.Prototype.Server/Services/FingerprintManager.cs b/Akari.Prototype.Server/Services/FingerprintManager.cs index af278dc..7b107fb 100644 --- a/Akari.Prototype.Server/Services/FingerprintManager.cs +++ b/Akari.Prototype.Server/Services/FingerprintManager.cs @@ -48,7 +48,7 @@ namespace Akari.Prototype.Server.Services // Load else { - _fingerprintsHash = JsonSerializer.Deserialize>(File.ReadAllText(path)); + _fingerprintsHash = JsonSerializer.Deserialize>(File.ReadAllText(path)); } } diff --git a/Akari.Prototype.Server/Services/IApplicationsManager.cs b/Akari.Prototype.Server/Services/IApplicationsManager.cs new file mode 100644 index 0000000..3408662 --- /dev/null +++ b/Akari.Prototype.Server/Services/IApplicationsManager.cs @@ -0,0 +1,18 @@ +using Akari.Prototype.Server.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Threading.Tasks; + +namespace Akari.Prototype.Server.Services +{ + public interface IApplicationsManager + { + bool TryCreate(string applicationName, out string token); + + bool AddFingerprint(string applicationName, string applicationToken, string fingerprintName, string masterPassword); + + bool TryRetrieveKey(string applicationName, string token, out AesGcm key); + } +} diff --git a/Akari.Prototype.Server/Services/IAuthManager.cs b/Akari.Prototype.Server/Services/IAuthManager.cs index ac28b5b..b32a23f 100644 --- a/Akari.Prototype.Server/Services/IAuthManager.cs +++ b/Akari.Prototype.Server/Services/IAuthManager.cs @@ -15,6 +15,8 @@ namespace Akari.Prototype.Server.Services void Auth(string name, byte[] token); + bool TryGetKey(string name, out AesGcm key); + bool Remove(string name); } } diff --git a/Akari.Prototype.Server/Startup.cs b/Akari.Prototype.Server/Startup.cs index e433b65..f15f093 100644 --- a/Akari.Prototype.Server/Startup.cs +++ b/Akari.Prototype.Server/Startup.cs @@ -47,6 +47,7 @@ namespace Akari.Prototype.Server services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); }