Implement IKeyManager
This commit is contained in:
@@ -1,11 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using Akari.Prototype.Server.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Akari.Prototype.Server.Services
|
||||
{
|
||||
public class KeyManager : IKeyManager
|
||||
public sealed class KeyManager : IKeyManager
|
||||
{
|
||||
public const string KeysPath = "Keys";
|
||||
public const int KeyLength = 256 / 8;
|
||||
|
||||
private readonly ILogger<KeyManager> _logger;
|
||||
private readonly IMasterKeyService _masterKeyService;
|
||||
private readonly AkariPath _akariPath;
|
||||
|
||||
public KeyManager(ILogger<KeyManager> logger, IMasterKeyService masterKeyService, AkariPath akariPath)
|
||||
{
|
||||
_logger = logger;
|
||||
_masterKeyService = masterKeyService;
|
||||
_akariPath = akariPath;
|
||||
|
||||
CheckConfig();
|
||||
}
|
||||
|
||||
private void CheckConfig()
|
||||
{
|
||||
string path = _akariPath.GetPath(KeysPath);
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddFingerprint(string applicationName, string fingerprintName, AesGcm fingerprintKey)
|
||||
{
|
||||
if (!Directory.Exists(GetKeyDirectoryPath(applicationName)) || !_masterKeyService.TryGetKey(out var masterKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read key
|
||||
var encryptedKeyBytes = File.ReadAllBytes(GetMasterKeyPath(applicationName));
|
||||
|
||||
var decryptedKeyBytes = Security.AesGcmDecrypt(masterKey, encryptedKeyBytes);
|
||||
|
||||
var newEncryptedKeyBytes = Security.AesGcmEncrypt(fingerprintKey, decryptedKeyBytes);
|
||||
|
||||
File.WriteAllBytes(GetKeyPath(applicationName, fingerprintName), newEncryptedKeyBytes);
|
||||
|
||||
_logger.LogDebug($"Fingerprint '{fingerprintName}' added for {applicationName}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Clear(string applicationName)
|
||||
{
|
||||
_logger.LogDebug($"Deleted keys for {applicationName}");
|
||||
|
||||
_logger.LogDebug($"Going to delete {GetKeyDirectoryPath(applicationName)}");
|
||||
//Directory.Delete(GetKeyDirectoryPath(applicationName));
|
||||
}
|
||||
|
||||
public bool Create(string applicationName)
|
||||
{
|
||||
if (!_masterKeyService.TryGetKey(out var masterKey))
|
||||
{
|
||||
_logger.LogDebug("Can't create key if master not logged in");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(GetKeyDirectoryPath(applicationName));
|
||||
|
||||
Span<byte> keyBytes = KeyLength <= 1024 ? stackalloc byte[KeyLength]
|
||||
: new byte[KeyLength];
|
||||
|
||||
RandomNumberGenerator.Fill(keyBytes);
|
||||
|
||||
var encryptedKeyBytes = Security.AesGcmEncrypt(masterKey, keyBytes);
|
||||
|
||||
File.WriteAllBytes(GetMasterKeyPath(applicationName), encryptedKeyBytes);
|
||||
|
||||
_logger.LogDebug($"Key created for {applicationName}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public AesGcm RetrieveKey(string applicationName, string fingerprintName, AesGcm fingerprintKey)
|
||||
{
|
||||
if (!Directory.Exists(GetKeyDirectoryPath(applicationName)))
|
||||
{
|
||||
throw new IOException($"Can't find key files for {applicationName}");
|
||||
}
|
||||
|
||||
// Read key
|
||||
var encryptedKeyBytes = File.ReadAllBytes(GetKeyPath(applicationName, fingerprintName));
|
||||
|
||||
var decryptedKeyBytes = Security.AesGcmDecrypt(fingerprintKey, encryptedKeyBytes);
|
||||
|
||||
_logger.LogDebug($"Key retrieved for {applicationName} using {fingerprintName}");
|
||||
|
||||
return new AesGcm(decryptedKeyBytes);
|
||||
}
|
||||
|
||||
private string GetKeyDirectoryPath(string applicationName) => Path.Combine(_akariPath.GetPath(KeysPath), applicationName);
|
||||
|
||||
private string GetMasterKeyPath(string applicationName) => Path.Combine(GetKeyDirectoryPath(applicationName), "key");
|
||||
|
||||
private string GetKeyPath(string applicationName, string fingerprintName) => $"{GetMasterKeyPath(applicationName)}-{fingerprintName}";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user