OSDN Git Service

GUI: Replaced the built-in password generator with call to SlunkCrypt CLI program...
authorLoRd_MuldeR <mulder2@gmx.de>
Tue, 8 Feb 2022 23:44:56 +0000 (00:44 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Wed, 9 Feb 2022 22:52:09 +0000 (23:52 +0100)
gui/App.config
gui/Process/ExecutableHelper.cs [new file with mode: 0644]
gui/Process/PasswordGen.cs [new file with mode: 0644]
gui/Process/SlunkCryptRunner.cs
gui/Properties/Settings.Designer.cs
gui/SlunkCryptGUI.csproj
gui/SlunkCryptGUI.xaml.cs
gui/Utilities/PathUtils.cs
gui/Utilities/SecureRandom.cs [deleted file]

index 87b3ead..58e53ce 100644 (file)
@@ -1,9 +1,9 @@
-<?xml version="1.0" encoding="utf-8" ?>
+<?xml version="1.0" encoding="utf-8"?>
 <configuration>
     <startup> 
-        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5/>
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
     </startup>
     <appSettings>
-        <add key="DisableBusyIndicator" value="false" />
+        <add key="DisableBusyIndicator" value="false"/>
     </appSettings>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/gui/Process/ExecutableHelper.cs b/gui/Process/ExecutableHelper.cs
new file mode 100644 (file)
index 0000000..31facdc
--- /dev/null
@@ -0,0 +1,79 @@
+/******************************************************************************/
+/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
+/* This work has been released under the CC0 1.0 Universal license!           */
+/******************************************************************************/
+
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using com.muldersoft.slunkcrypt.gui.utils;
+
+namespace com.muldersoft.slunkcrypt.gui.process
+{
+    static class ExecutableHelper
+    {
+        private const string FILENAME_FORMAT = "slunkcrypt-cli-{0}.exe";
+
+        // =============================================================================
+        // Exception classes
+        // =============================================================================
+
+        public class ExecutableNotFoundException : FileNotFoundException
+        {
+            public ExecutableNotFoundException(string message, string fileName) : base(message, fileName)
+            {
+            }
+        }
+        
+        // =============================================================================
+        // Public methods
+        // =============================================================================
+
+        public static FileStream GetExecutableFile()
+        {
+            FileStream executableFile = null;
+            string appBaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
+            CPUFeatures cpuFeatures = CPUFeatures.Features;
+            if (cpuFeatures.x64 && CheckExecutableFile(ref executableFile, appBaseDirectory, "x64"))
+            {
+                Trace.Assert(executableFile != null);
+                return executableFile;
+            }
+            if (cpuFeatures.sse2 && CheckExecutableFile(ref executableFile, appBaseDirectory, "sse2"))
+            {
+                Trace.Assert(executableFile != null);
+                return executableFile;
+            }
+            if (CheckExecutableFile(ref executableFile, appBaseDirectory, "i686"))
+            {
+                Trace.Assert(executableFile != null);
+                return executableFile;
+            }
+            throw new ExecutableNotFoundException("SlunkCrypt executable file not found!", FILENAME_FORMAT);
+        }
+
+        // =============================================================================
+        // Internal methods
+        // =============================================================================
+
+        private static bool CheckExecutableFile(ref FileStream executableFile, string appBaseDirectory, string suffix)
+        {
+            try
+            {
+                executableFile = new FileStream(Path.Combine(appBaseDirectory, String.Format(FILENAME_FORMAT, suffix)), FileMode.Open, FileAccess.Read, FileShare.Read);
+                Version appVersion = VersionInfo.Version;
+                FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(executableFile.Name);
+                if (string.Equals(fileVersion.FileDescription, "SlunkCrypt", StringComparison.OrdinalIgnoreCase) &&
+                    string.Equals(fileVersion.CompanyName, "Muldersoft", StringComparison.OrdinalIgnoreCase) &&
+                    (fileVersion.FileMajorPart == appVersion.Major) && (fileVersion.FileMinorPart == appVersion.Minor))
+                {
+                    return true;
+                }
+                executableFile.Dispose(); /*clean-up*/
+            }
+            catch { }
+            return false;
+        }
+    }
+}
diff --git a/gui/Process/PasswordGen.cs b/gui/Process/PasswordGen.cs
new file mode 100644 (file)
index 0000000..9592b0f
--- /dev/null
@@ -0,0 +1,139 @@
+/******************************************************************************/
+/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
+/* This work has been released under the CC0 1.0 Universal license!           */
+/******************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace com.muldersoft.slunkcrypt.gui.process
+{
+    public static class PasswordGen
+    {
+        private static readonly TimeSpan TIMEOUT_MSEC = TimeSpan.FromSeconds(90);
+
+        private const string COMMAND_PASSWRD = "-p {0:D}";
+
+        // =============================================================================
+        // Exception classes
+        // =============================================================================
+
+        public class GenerationFailedException : IOException
+        {
+            public GenerationFailedException(string message, Exception innerException) : base(message, innerException)
+            {
+            }
+        }
+
+        // =============================================================================
+        // Public methods
+        // =============================================================================
+
+        public static async Task<string> GeneratePassword(int length)
+        {
+            using (FileStream executableFile = ExecutableHelper.GetExecutableFile())
+            {
+                try
+                {
+                    string password = await StartProcess(executableFile, length);
+                    if (IsWeakPassword(password))
+                    {
+                        throw new InvalidDataException("The generated password string is invalid!");
+                    }
+                    return password;
+                }
+                catch (Exception e)
+                {
+                    throw new GenerationFailedException("Failed to generate password string!", e);
+                }
+            }
+        }
+
+        public static bool IsWeakPassword(string password)
+        {
+            int flags = 0;
+            if (!string.IsNullOrEmpty(password))
+            {
+                foreach (char c in password)
+                {
+                    if (char.IsLetter(c))
+                    {
+                        flags |= char.IsUpper(c) ? 0x2 : 0x1;
+                    }
+                    else
+                    {
+                        flags |= char.IsDigit(c) ? 0x8 : 0x4;
+                    }
+                }
+            }
+            return (flags != 0xF);
+        }
+
+        // =============================================================================
+        // Internal methods
+        // =============================================================================
+
+        private static async Task<string> StartProcess(FileStream executableFile, int length)
+        {
+            using (Process process = new Process())
+            {
+                process.StartInfo.UseShellExecute = false;
+                process.StartInfo.CreateNoWindow = true;
+                process.StartInfo.RedirectStandardOutput = true;
+                process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
+                process.StartInfo.FileName = executableFile.Name;
+                process.StartInfo.Arguments = string.Format(COMMAND_PASSWRD, length);
+                process.Start();
+
+                Stack<string> outputLines = await WaitForExit(process, TIMEOUT_MSEC);
+
+                if (process.ExitCode == 0)
+                {
+                    while (outputLines.Count > 0)
+                    {
+                        string line = outputLines.Pop();
+                        if (line.Length >= length)
+                        {
+                            return line;
+                        }
+                    }
+                }
+                return string.Empty;
+            }
+        }
+
+        private static async Task<Stack<string>> WaitForExit(Process process, TimeSpan timeout)
+        {
+            Task<Stack<string>> readTask;
+            await Task.WhenAny(readTask = Task.Run(() => ReadOutput(process)), Task.Delay(timeout));
+            if (!process.WaitForExit(125))
+            {
+                process.Kill();
+                process.WaitForExit();
+            }
+            return await readTask;
+        }
+
+        private static Stack<string> ReadOutput(Process process)
+        {
+            Stack<string> result = new Stack<string>();
+            using (StreamReader reader = process.StandardOutput)
+            {
+                string line;
+                while ((line = reader.ReadLine()) != null)
+                {
+                    line = line.Trim();
+                    if (line.Length != 0)
+                    {
+                        result.Push(line.Trim());
+                    }
+                }
+            }
+            return result;
+        }
+    }
+}
index 6979a06..fabd8b0 100644 (file)
@@ -20,7 +20,6 @@ namespace com.muldersoft.slunkcrypt.gui.process
     {
         public enum Mode { Encrypt, Decrypt }
 
-        private const string FILENAME_FORMAT = "slunkcrypt-cli-{0}.exe";
         private const string COMMAND_ENCRYPT = "-e";
         private const string COMMAND_DECRYPT = "-d";
 
@@ -29,23 +28,12 @@ namespace com.muldersoft.slunkcrypt.gui.process
         private readonly FileStream m_executableFile;
 
         // =============================================================================
-        // Exception classes
-        // =============================================================================
-
-        public class ExecutableNotFoundException : FileNotFoundException
-        {
-            public ExecutableNotFoundException(string message, string fileName) : base(message, fileName)
-            {
-            }
-        }
-
-        // =============================================================================
         // Constructor
         // =============================================================================
 
         public SlunkCryptRunner(Dispatcher dispatcher, ProcessPriorityClass? priorityClass = null) : base(dispatcher, priorityClass)
         {
-            m_executableFile = GetExecutableFile();
+            m_executableFile = ExecutableHelper.GetExecutableFile();
         }
 
         // =============================================================================
@@ -74,48 +62,6 @@ namespace com.muldersoft.slunkcrypt.gui.process
         // Internal methods
         // =============================================================================
 
-        private static FileStream GetExecutableFile()
-        {
-            FileStream executableFile = null;
-            string appBaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
-            CPUFeatures cpuFeatures = CPUFeatures.Features;
-            if (cpuFeatures.x64 && CheckExecutableFile(ref executableFile, appBaseDirectory, "x64"))
-            {
-                Trace.Assert(executableFile != null);
-                return executableFile;
-            }
-            if (cpuFeatures.sse2 && CheckExecutableFile(ref executableFile, appBaseDirectory, "sse2"))
-            {
-                Trace.Assert(executableFile != null);
-                return executableFile;
-            }
-            if (CheckExecutableFile(ref executableFile, appBaseDirectory, "i686"))
-            {
-                Trace.Assert(executableFile != null);
-                return executableFile;
-            }
-            throw new ExecutableNotFoundException("SlunkCrypt executable file not found!", FILENAME_FORMAT);
-        }
-
-        private static bool CheckExecutableFile(ref FileStream executableFile, string appBaseDirectory, string suffix)
-        {
-            try
-            {
-                executableFile = new FileStream(Path.Combine(appBaseDirectory, String.Format(FILENAME_FORMAT, suffix)), FileMode.Open, FileAccess.Read, FileShare.Read);
-                Version appVersion = VersionInfo.Version;
-                FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(executableFile.Name);
-                if (string.Equals(fileVersion.FileDescription, "SlunkCrypt", StringComparison.OrdinalIgnoreCase) &&
-                    string.Equals(fileVersion.CompanyName, "Muldersoft", StringComparison.OrdinalIgnoreCase) &&
-                    (fileVersion.FileMajorPart == appVersion.Major) && (fileVersion.FileMinorPart == appVersion.Minor))
-                {
-                    return true;
-                }
-                executableFile.Dispose(); /*clean-up*/
-            }
-            catch { }
-            return false;
-        }
-
         protected override double ParseProgressString(StringBuilder currentLine)
         {
             Match match;
index 6cb913f..6c3c7dd 100644 (file)
@@ -12,7 +12,7 @@ namespace com.muldersoft.slunkcrypt.gui.Properties {
     
     
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
     internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
         
         private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
index d320e15..417d997 100644 (file)
@@ -9,10 +9,11 @@
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>com.muldersoft.slunkcrypt.gui</RootNamespace>
     <AssemblyName>slunkcrypt-gui</AssemblyName>
-    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
     <WarningLevel>4</WarningLevel>
+    <TargetFrameworkProfile />
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
     <Compile Include="Controls\PasswordToggleBox.xaml.cs">
       <DependentUpon>PasswordToggleBox.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Process\ExecutableHelper.cs" />
     <Compile Include="Utilities\ApplicationConfig.cs" />
     <Compile Include="Utilities\CPUFeatures.cs" />
     <Compile Include="Process\SlunkCryptRunner.cs" />
     <Compile Include="Utilities\BusyManager.cs" />
     <Compile Include="Utilities\CPU\CPUCapabilities.cs" />
+    <Compile Include="Process\PasswordGen.cs" />
     <Compile Include="Utilities\PathUtils.cs" />
-    <Compile Include="Utilities\SecureRandom.cs" />
     <Compile Include="Utilities\SystemMenu.cs" />
     <Compile Include="Utilities\VisibilityConverter.cs" />
     <Compile Include="Utilities\FontSizeConverter.cs" />
index c41e4af..1c0a5a3 100644 (file)
@@ -50,7 +50,7 @@ namespace com.muldersoft.slunkcrypt.gui
         private volatile SlunkCryptRunner m_processRunner = null;
         private uint? m_menuId_disableAnimation = null, m_menuId_enableExpertMode = null;
 
-        private const string ASCII_CHARS = "!#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+        public const string ASCII_CHARS = "!#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";
 
         // =============================================================================
         // Constructor
@@ -159,10 +159,12 @@ namespace com.muldersoft.slunkcrypt.gui
             using (BusyManager busy = new BusyManager(this))
             {
                 Edit_Encrypt_Password.Password = string.Empty;
-                Task<string> password = Task.Run(() => GenerateRandomString(GEN_PASSWD_LENGTH));
-                await Task.WhenAll(password, Task.Delay(500));
-                Button_Encrypt_Toggle.IsChecked = true;
-                Edit_Encrypt_Password.Password = password.Result;
+                string password;
+                if (!string.IsNullOrEmpty(password = await GeneratePassword()))
+                {
+                    Button_Encrypt_Toggle.IsChecked = true;
+                    Edit_Encrypt_Password.Password = password;
+                }
             }
         }
 
@@ -532,7 +534,7 @@ namespace com.muldersoft.slunkcrypt.gui
                         return;
                     }
                 }
-                else if (IsWeakPassword(passwordStr))
+                else if (PasswordGen.IsWeakPassword(passwordStr))
                 {
                     if (MessageBox.Show(this, "Passphrase should contain a mix of upper case characters, lower case characters, digits and other characters!", "Weak Passphrase", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel) != MessageBoxResult.OK)
                     {
@@ -635,7 +637,7 @@ namespace com.muldersoft.slunkcrypt.gui
                 SetStatus(string.Format("Error: The {0} process could not be created! (Error code: {1:D})", GetModeString(m_modeOfOperation), GetWin32ErrorCode(err)), Status.Failure);
                 MessageBox.Show(this, "Failed to create SlunkCrypt process:\n\n" + err.InnerException?.Message ?? err.Message, "Process Creation Error", MessageBoxButton.OK, MessageBoxImage.Error);
             }
-            catch (SlunkCryptRunner.ExecutableNotFoundException)
+            catch (ExecutableHelper.ExecutableNotFoundException)
             {
                 SetStatus("Error: The required SlunkCrypt executable file could not be found!", Status.Failure);
                 MessageBox.Show(this, "The SlunkCrypt executable file could not be found.\n\nPlease make sure that the SlunkCrypt CLI executable file is located in the same directory as the GUI program!", "Executable Not Found", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -652,6 +654,26 @@ namespace com.muldersoft.slunkcrypt.gui
             return null;
         }
 
+        private async Task<string> GeneratePassword()
+        {
+            string password = string.Empty;
+            try
+            {
+                Task<string> passwordTask = Task.Run(() => PasswordGen.GeneratePassword(GEN_PASSWD_LENGTH));
+                await Task.WhenAll(passwordTask, Task.Delay(1000));
+                password = passwordTask.Result;
+            }
+            catch (ExecutableHelper.ExecutableNotFoundException)
+            {
+                MessageBox.Show(this, "The SlunkCrypt executable file could not be found.\n\nPlease make sure that the SlunkCrypt CLI executable file is located in the same directory as the GUI program!", "Executable Not Found", MessageBoxButton.OK, MessageBoxImage.Error);
+            }
+            catch (PasswordGen.GenerationFailedException)
+            {
+                MessageBox.Show(this, "Error: The password could not be generated!", "Generation Failed", MessageBoxButton.OK, MessageBoxImage.Error);
+            }
+            return password;
+        }
+
         private void SetStatus(string text, Status status = Status.Default)
         {
             switch (status)
@@ -891,47 +913,6 @@ namespace com.muldersoft.slunkcrypt.gui
             }
         }
 
-        private static bool IsWeakPassword(string password)
-        {
-            int flags = 0;
-            foreach (char c in password)
-            {
-                if (char.IsLetter(c))
-                {
-                    flags |= char.IsUpper(c) ? 0x2 : 0x1;
-                }
-                else
-                {
-                    flags |= char.IsDigit(c) ? 0x8 : 0x4;
-                }
-            }
-            return (flags != 0xF);
-        }
-
-        private static string GenerateRandomString(int length)
-        {
-            if (length > 0)
-            {
-                char[] asciiChars = ASCII_CHARS.ToCharArray();
-                using (SecureRandom secureRandom = new SecureRandom())
-                {
-                    string result;
-                    do
-                    {
-                        StringBuilder builder = new StringBuilder();
-                        for (int i = 0; i < length; ++i)
-                        {
-                            builder.Append(asciiChars[secureRandom.NextUInt32() % ((uint)asciiChars.Length)]);
-                        }
-                        result = builder.ToString();
-                    }
-                    while ((!char.IsLetterOrDigit(result[0])) || (!char.IsLetterOrDigit(result[result.Length - 1])) || IsWeakPassword(result));
-                    return result;
-                }
-            }
-            return string.Empty;
-        }
-
         private static void SetFocusAndSelectAll(FrameworkElement element)
         {
             TextBox textBox;
index a3b65a5..66fb742 100644 (file)
@@ -209,6 +209,5 @@ namespace com.muldersoft.slunkcrypt.gui.utils
         {
             return ((c == WILDCARD_ONE) || (c == WILDCARD_ANY));
         }
-
     }
 }
diff --git a/gui/Utilities/SecureRandom.cs b/gui/Utilities/SecureRandom.cs
deleted file mode 100644 (file)
index 4d06694..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/******************************************************************************/
-/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
-/* This work has been released under the CC0 1.0 Universal license!           */
-/******************************************************************************/
-
-using System;
-using System.IO;
-using System.Security.Cryptography;
-
-namespace com.muldersoft.slunkcrypt.gui.utils
-{
-    class SecureRandom : IDisposable
-    {
-        private volatile bool m_disposed = false;
-
-        private readonly RNGCryptoServiceProvider m_provider;
-        private readonly byte[] m_tempBuffer = new byte[256];
-
-        private int m_offset = int.MaxValue;
-
-        // =============================================================================
-        // Constructor
-        // =============================================================================
-
-        public SecureRandom()
-        {
-            try
-            {
-                m_provider = new RNGCryptoServiceProvider();
-            }
-            catch (Exception e)
-            {
-                throw new IOException("Failed to create RNGCryptoServiceProvider instance!", e);
-            }
-        }
-
-        ~SecureRandom()
-        {
-            Dispose();
-        }
-
-        // =============================================================================
-        // Public methods
-        // =============================================================================
-
-        public int NextInt32()
-        {
-            if (m_disposed)
-            {
-                throw new ObjectDisposedException("SecureRandom");
-            }
-            EnsureBytesAvailable(sizeof(int));
-            int value = BitConverter.ToInt32(m_tempBuffer, m_offset);
-            m_offset += sizeof(int);
-            return value;
-        }
-
-        public uint NextUInt32()
-        {
-            if (m_disposed)
-            {
-                throw new ObjectDisposedException("SecureRandom");
-            }
-            EnsureBytesAvailable(sizeof(uint));
-            uint value = BitConverter.ToUInt32(m_tempBuffer, m_offset);
-            m_offset += sizeof(uint);
-            return value;
-        }
-
-        public long NextInt64()
-        {
-            if (m_disposed)
-            {
-                throw new ObjectDisposedException("SecureRandom");
-            }
-            EnsureBytesAvailable(sizeof(long));
-            long value = BitConverter.ToInt64(m_tempBuffer, m_offset);
-            m_offset += sizeof(long);
-            return value;
-        }
-
-        public ulong NextUInt64()
-        {
-            if (m_disposed)
-            {
-                throw new ObjectDisposedException("SecureRandom");
-            }
-            EnsureBytesAvailable(sizeof(ulong));
-            ulong value = BitConverter.ToUInt64(m_tempBuffer, m_offset);
-            m_offset += sizeof(ulong);
-            return value;
-        }
-
-        public void Dispose()
-        {
-            if (!m_disposed)
-            {
-                m_disposed = true;
-                GC.SuppressFinalize(this);
-                try
-                {
-                    FillArray(m_tempBuffer, 0);
-                }
-                finally
-                {
-                    try
-                    {
-                        m_provider.Dispose();
-                    }
-                    catch { }
-                }
-            }
-        }
-
-        // =============================================================================
-        // Internal methods
-        // =============================================================================
-
-        private void EnsureBytesAvailable(int length)
-        {
-            if ((m_offset >= m_tempBuffer.Length) || ((m_tempBuffer.Length - m_offset) < length))
-            {
-                try
-                {
-                    m_provider.GetBytes(m_tempBuffer);
-                    m_offset = 0;
-                }
-                catch (Exception e)
-                {
-                    throw new IOException("Failed to generated random bytes!", e);
-                }
-            }
-        }
-
-        private static void FillArray(byte[] array, byte value)
-        {
-            if (!ReferenceEquals(array, null))
-            {
-                for (int i = 0; i < array.Length; ++i)
-                {
-                    array[i] = value;
-                }
-            }
-        }
-    }
-}