internal static byte[] GenerateKeyFile(ITestOutputHelper output, IKeyCapture capture, IKeyFileService service)
 {
     lock (Sync)
     {
         var @out  = new XunitDuplexTextWriter(output, Console.Out);
         var error = new XunitDuplexTextWriter(output, Console.Error);
         Assert.True(KeyFileManager.TryGenerateKeyFile(service.GetKeyFileStream(), @out, error, capture));
         capture.Reset();
         return(Crypto.SigningPublicKeyFromSigningKey(service, capture));
     }
 }
示例#2
0
        public void Fails_password_capture_when_confirm_password_is_incorrect(string plaintext, string plaintextConfirm = null)
        {
            var capture = new PlaintextKeyCapture(plaintext, plaintextConfirm ?? $"{plaintext}wrong");

            unsafe
            {
                var result = KeyFileManager.TryCapturePassword("test", capture, Console.Out, Console.Error, out var password, out var passwordLength);
                Assert.False(result);
                Assert.True(password == default(byte *));
            }
        }
示例#3
0
        public void Fails_password_capture_with_empty_confirm_password(string plaintext)
        {
            var capture = new PlaintextKeyCapture(plaintext, string.Empty);

            unsafe
            {
                var result = KeyFileManager.TryCapturePassword("test", capture, Console.Out, Console.Error,
                                                               out var password, out var passwordLength);
                Assert.False(result);
                Assert.NotEqual(plaintext.Length, passwordLength);
                NativeMethods.sodium_free(password);
            }
        }
示例#4
0
        public void Succeeds_password_capture_when_password_is_confirmed_correctly(string plaintext,
                                                                                   string plaintextConfirm = null)
        {
            var capture = new PlaintextKeyCapture(plaintext, plaintextConfirm ?? plaintext);

            unsafe
            {
                var result = KeyFileManager.TryCapturePassword("test", capture, Console.Out, Console.Error,
                                                               out var password, out var passwordLength);
                Assert.True(result);
                Assert.Equal(plaintext.Length, passwordLength);
                NativeMethods.sodium_free(password);
            }
        }
示例#5
0
        protected override IHostBuilder CreateHostBuilder()
        {
            var keyFilePath = Path.GetTempFileName();
            var eggPath     = Path.GetTempFileName();

            File.WriteAllBytes(keyFilePath, new byte[KeyFileManager.KeyFileBytes]);

            var         password = $"{Guid.NewGuid()}";
            IKeyCapture capture  = new PlaintextKeyCapture(password, password);

            Assert.True(KeyFileManager.Create(keyFilePath, false, true, capture));

            Crypto.Initialize();
            Program.keyFilePath   = keyFilePath;
            Program.keyFileStream = new FileStream(Program.keyFilePath, FileMode.Open, FileAccess.Read, FileShare.None);

            return(Program.CreateHostBuilder(null, eggPath, capture));
        }
示例#6
0
        public void Can_save_and_load_key_file_with_correct_password(string plaintext)
        {
            unsafe
            {
                var keyFilePath   = Path.GetTempFileName();
                var keyFileStream = File.Open(keyFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);

                var @out  = new XunitDuplexTextWriter(_output, Console.Out);
                var error = new XunitDuplexTextWriter(_output, Console.Error);

                var generatedKeyFile = KeyFileManager.TryGenerateKeyFile(keyFileStream, @out, error,
                                                                         new PlaintextKeyCapture(plaintext, plaintext));
                Assert.True(generatedKeyFile);

                keyFileStream.Dispose();
                keyFileStream = File.OpenRead(keyFilePath);

                var loadedKeyFile = KeyFileManager.TryLoadKeyFile(keyFileStream, @out, error, out var secretKey,
                                                                  new PlaintextKeyCapture(plaintext, plaintext));
                Assert.True(loadedKeyFile);
                NativeMethods.sodium_free(secretKey);
            }
        }
示例#7
0
        public void Cannot_load_saved_key_file_with_incorrect_password(string plaintext)
        {
            unsafe
            {
                var keyFilePath   = Path.GetTempFileName();
                var keyFileStream = File.Open(keyFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite,
                                              FileShare.ReadWrite);

                var @out  = new XunitDuplexTextWriter(_output, Console.Out);
                var error = new XunitDuplexTextWriter(_output, Console.Error);

                var generatedKeyFile = KeyFileManager.TryGenerateKeyFile(keyFileStream, @out, error,
                                                                         new PlaintextKeyCapture(plaintext, plaintext));
                Assert.True(generatedKeyFile, nameof(generatedKeyFile));

                keyFileStream.Dispose();
                keyFileStream = File.OpenRead(keyFilePath);

                var loadedKeyFile = KeyFileManager.TryLoadKeyFile(keyFileStream, @out, error, out var secretKey,
                                                                  new PlaintextKeyCapture($"{plaintext}wrong", $"{plaintext}wrong"));
                Assert.False(loadedKeyFile, nameof(loadedKeyFile));
                Assert.True(secretKey == default(byte *), nameof(secretKey));
            }
        }
示例#8
0
        private static bool ProcessCommandLineArguments(Queue <string> arguments)
        {
            while (arguments.Count > 0)
            {
                var arg = arguments.Dequeue();
                switch (arg.ToLower())
                {
                    #region Unattended Commands

                case "--nolock":
                    _exclusiveLock = false;
                    break;

                case "--port":
                case "-p":
                {
                    var portString = arguments.Dequeue();
                    int.TryParse(portString, out _port);
                    break;
                }

                    #endregion

                    #region CLI Commands

                case "--cert":
                case "--certs":
                case "-c":
                {
                    var freshOrClear = arguments.EndOfSubArguments() ? "false" : arguments.Dequeue();
                    if (freshOrClear?.Equals("clear", StringComparison.OrdinalIgnoreCase) ?? false)
                    {
                        CertificateBuilder.ClearAll(Console.Out);
                    }
                    else
                    {
                        CertificateBuilder.GetOrCreateSelfSignedCert(Console.Out,
                                                                     freshOrClear?.Equals("fresh", StringComparison.OrdinalIgnoreCase) ?? false);
                    }
                    return(false);
                }

                case "--egg":
                case "-e":
                {
                    var eggPath = arguments.EndOfSubArguments() ? Constants.DefaultEggPath : arguments.Dequeue();
                    EggFileManager.Create(eggPath);
                    return(false);
                }

                case "--keygen":
                case "-k":
                {
                    var keyPath = arguments.EndOfSubArguments()
                            ? Constants.DefaultKeyFilePath
                            : arguments.Dequeue();
                    KeyFileManager.Create(keyPath, true, false, Constants.ConsoleKeyCapture);
                    return(false);
                }

                case "--server":
                case "-s":
                {
                    RunAsServer(null, arguments, null, true);
                    return(false);
                }

                    #endregion
                }
            }

            return(true);
        }
示例#9
0
        private static void RunAsServer(int?port, Queue <string> arguments, IKeyCapture capture, bool interactive)
        {
            var keyPath = arguments.EndOfSubArguments() ? Constants.DefaultKeyFilePath : arguments.Dequeue();

            if (!KeyFileManager.TryResolveKeyPath(keyPath, out keyFilePath, false, true))
            {
                return;
            }

            var shouldCreateKeyFile = !File.Exists(keyFilePath) || new FileInfo(keyFilePath).Length == 0;

            if (shouldCreateKeyFile)
            {
                File.WriteAllBytes(keyFilePath, new byte[KeyFileManager.KeyFileBytes]);
            }

            Console.Out.WriteInfoLine($"Key file path resolved to '{keyFilePath}'");

            if (shouldCreateKeyFile &&
                !KeyFileManager.Create(keyFilePath, false, true, capture ?? Constants.ConsoleKeyCapture))
            {
                Console.Error.WriteErrorLine("Cannot start server without a key file");
                return;
            }

            if (_exclusiveLock)
            {
                try
                {
                    keyFileStream = new FileStream(keyFilePath, FileMode.Open, FileAccess.Read, FileShare.None);
                }
                catch (IOException)
                {
                    Console.Error.WriteErrorLine("Could not obtain exclusive lock on key file");
                    return;
                }
            }
            else
            {
                try
                {
                    keyFileStream = new FileStream(keyFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                }
                catch (IOException)
                {
                    Console.Error.WriteErrorLine("Could not open key file");
                    return;
                }
            }

            var eggPath = Environment.GetEnvironmentVariable(Constants.EnvVars.EggFilePath);

            if (string.IsNullOrWhiteSpace(eggPath))
            {
                eggPath = Constants.DefaultEggPath;
            }

            Console.Out.WriteInfoLine($"Egg file path resolved to '{eggPath}'");

            if (!File.Exists(eggPath) && !EggFileManager.Create(eggPath))
            {
                Console.Error.WriteWarningLine("Server started without an egg");
            }

            capture?.Reset();

            if (!interactive)
            {
                LaunchBrowserUrl($"https://localhost:{port.GetValueOrDefault(Constants.DefaultPort)}");
            }

            PrintMasthead();
            var builder = CreateHostBuilder(port, eggPath, capture, arguments.ToArray());
            var host    = builder.Build();

            host.Run();
        }