using NetMQ; using Phantom.Common.Data; using Phantom.Utils.Cryptography; using Phantom.Utils.IO; using Phantom.Utils.Logging; using ILogger = Serilog.ILogger; namespace Phantom.Web; static class WebKey { private static ILogger Logger { get; } = PhantomLogger.Create(nameof(WebKey)); public static Task<(NetMQCertificate, AuthToken)?> Load(string? webKeyToken, string? webKeyFilePath) { if (webKeyFilePath != null) { return LoadFromFile(webKeyFilePath); } else if (webKeyToken != null) { return Task.FromResult(LoadFromToken(webKeyToken)); } else { throw new InvalidOperationException(); } } private static async Task<(NetMQCertificate, AuthToken)?> LoadFromFile(string webKeyFilePath) { if (!File.Exists(webKeyFilePath)) { Logger.Fatal("Missing web key file: {WebKeyFilePath}", webKeyFilePath); return null; } try { Files.RequireMaximumFileSize(webKeyFilePath, 64); return LoadFromBytes(await File.ReadAllBytesAsync(webKeyFilePath)); } catch (IOException e) { Logger.Fatal("Error loading web key from file: {WebKeyFilePath}", webKeyFilePath); Logger.Fatal(e.Message); return null; } catch (Exception) { Logger.Fatal("File does not contain a valid web key: {WebKeyFilePath}", webKeyFilePath); return null; } } private static (NetMQCertificate, AuthToken)? LoadFromToken(string webKey) { try { return LoadFromBytes(TokenGenerator.DecodeBytes(webKey)); } catch (Exception) { Logger.Fatal("Invalid web key: {WebKey}", webKey); return null; } } private static (NetMQCertificate, AuthToken)? LoadFromBytes(byte[] webKey) { var (publicKey, webToken) = ConnectionCommonKey.FromBytes(webKey); var controllerCertificate = NetMQCertificate.FromPublicKey(publicKey); Logger.Information("Loaded web key."); return (controllerCertificate, webToken); } }