Implement IKeyManager

This commit is contained in:
2021-06-07 01:44:47 +02:00
parent efbac54600
commit f539455e10
7 changed files with 331 additions and 55 deletions

View File

@@ -3,6 +3,7 @@ using Akari.Prototype.Server.Utils;
using Isopoh.Cryptography.Argon2;
using Microsoft.Extensions.Logging;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -12,7 +13,7 @@ using System.Threading.Tasks;
namespace Akari.Prototype.Server.Services
{
public class ApplicationsManager : IApplicationsManager
public sealed class ApplicationsManager : IApplicationsManager
{
public const string ApplicationsPath = "applications.json";
public const int ApplicationTokenLength = 18;
@@ -20,15 +21,17 @@ namespace Akari.Prototype.Server.Services
private readonly ILogger<ApplicationsManager> _logger;
private readonly IKeyManager _keyManager;
private readonly IAuthManager _authManager;
private readonly IMasterKeyService _masterKeyService;
private readonly AkariPath _akariPath;
private IDictionary<string, Application> _applications;
public ApplicationsManager(ILogger<ApplicationsManager> logger, IKeyManager keyManager, IAuthManager authManager, AkariPath akariPath)
public ApplicationsManager(ILogger<ApplicationsManager> logger, IKeyManager keyManager, IAuthManager authManager, IMasterKeyService masterKeyService, AkariPath akariPath)
{
_logger = logger;
_keyManager = keyManager;
_authManager = authManager;
_masterKeyService = masterKeyService;
_akariPath = akariPath;
LoadApplications();
@@ -57,56 +60,27 @@ namespace Akari.Prototype.Server.Services
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)
public bool TryCreate(string applicationName, out string applicationToken)
{
if (_applications.ContainsKey(applicationName))
{
_logger.LogDebug($"Can't create '{applicationName}' as it already exists");
token = null;
applicationToken = null;
return false;
}
if (!_masterKeyService.IsLoggedIn)
{
_logger.LogDebug("Can't create an application if master service is not logged in");
applicationToken = null;
return false;
}
// Application token
var tokenData = new byte[ApplicationTokenLength];
RandomNumberGenerator.Fill(tokenData);
@@ -117,7 +91,10 @@ namespace Akari.Prototype.Server.Services
_applications[applicationName] = application;
token = Convert.ToBase64String(tokenData);
applicationToken = Convert.ToBase64String(tokenData);
// Application key
_keyManager.Create(applicationName);
SaveApplications();
@@ -126,23 +103,102 @@ namespace Akari.Prototype.Server.Services
return true;
}
public bool TryRetrieveKey(string applicationName, string token, out AesGcm key)
public bool Contains(string applicationName)
{
key = null;
return _applications.ContainsKey(applicationName);
}
public bool Remove(string applicationName)
{
if (!_applications.ContainsKey(applicationName))
{
_logger.LogDebug($"Can't remove non existing application: {applicationName}");
return false;
}
// Clear keys
_keyManager.Clear(applicationName);
_applications.Remove(applicationName);
SaveApplications();
return true;
}
public bool AddFingerprint(string applicationName, string fingerprintName)
{
// Verify master password
if (!_masterKeyService.IsLoggedIn)
{
_logger.LogDebug($"Can't add a fingerprint for {applicationName} if master service is not logged in");
}
// 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);
_applications[applicationName].Fingerprints.Add(fingerprintName);
SaveApplications();
return true;
}
private bool VerifyToken(string applicationName, string applicationToken)
{
if (!_applications.TryGetValue(applicationName, out var application))
{
return false;
}
if (!VerifyToken(applicationName, token))
return Argon2.Verify(application.TokenHash, Convert.FromBase64String(applicationToken));
}
public bool TryRetrieveKey(string applicationName, string applicationToken, out AesGcm applicationKey)
{
applicationKey = null;
if (!_applications.TryGetValue(applicationName, out var application))
{
_logger.LogDebug($"Tried to retrieve key for non existing application: {applicationName}");
return false;
}
//key = _authManager.Retrieve(applicationName);
if (!VerifyToken(applicationName, applicationToken))
{
_logger.LogDebug($"Can't retrieve '{applicationName}' key, wrong token");
return false;
}
if (!_authManager.TryGetKey(application.Fingerprints, out var fingerprintName, out var fingerprintKey))
{
_logger.LogDebug($"Can't retrieve '{applicationName}' key, no fingerprint auth found");
}
applicationKey = _keyManager.RetrieveKey(applicationName, fingerprintName, fingerprintKey);
return true;
}
public IEnumerator<Application> GetEnumerator()
{
return _applications.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}